/* ==========================================================================
   daily-brief.css - the sample brief page, and nothing else loads it.

   WHAT THIS PAGE IS. tools.html sells the Daily Sector Brief in a card. This
   page hands the visitor one, made against a name they type, before they give
   an address. It is the only page on the site whose main content is generated
   at runtime, and that is deliberate rather than a lapse from the standing
   rule: the pitch, the "what is in one" list and the closer are all real
   markup and are what a crawler reads. What JavaScript builds is the SPECIMEN
   - a worked example that is invented by definition and says so in the note at
   the foot of it.

   WHITE LABEL. Same rule as tools.html, and it is the reason this page exists
   as its own file rather than as the prototype in tools/ dropped into place:
   that prototype carries the provider's product name, wordmark and palette on
   every screen. The provider is named in docs/brief.md and appears nowhere in
   this sheet, in daily-brief.html, in js/daily-brief.js, or in a comment in
   any of them.

   TOKENS, NOT VALUES. Everything here is base.css's own scale. The one thing
   this sheet declares of its own is the sentiment triple, and it is mixed from
   --green and --red rather than picked, so a brand change carries it.

   NO MONOSPACE, AND THAT IS THE CORRECTION OF A REAL DRIFT. This sheet carried
   fifteen uses of --mono against one in base.css and one to three in every other
   stylesheet on the site - the page had quietly declared a second typographic
   voice for itself. Mono was doing two jobs here and neither of them needed it:

     1. LINING UP NUMBERS. That is font-variant-numeric:tabular-nums, which
        Libre Franklin has. Every figure, hour, count and percentage on this page
        still sits on one vertical; it just does it in the site's own typeface.
     2. SAYING "THIS IS A LABEL". The site already has one idiom for that and it
        is .eyebrow - 12/18, weight 500, .14em, uppercase. Every micro-label here
        now takes those exact values rather than a near-miss of them, which also
        retired four different letter-spacings (.04, .06, .08, .09em) that were
        four answers to one question.

   Body sizes went UP a step where mono had been sized down to compensate for its
   larger apparent width: the log 15 -> 16, the time anchor 14 -> 15, the keyword
   chips 12 -> 13. Same optical size, one less typeface.
   ========================================================================== */

.db{
  /* Derived, not picked. --green and --red are base.css's semantic pair; the
     neutral is --ash so the three read as one family. The soft grounds are the
     same three at 12%, the lightest tint that still holds a boundary against
     --white, and the ink on them is darkened because --green at 16px on its
     own tint does not clear 4.5:1. */
  --pos:var(--green);
  --neu:var(--ash);
  --neg:var(--red);
  --pos-soft:color-mix(in srgb,var(--green) 12%,var(--white));
  --neu-soft:var(--mist);
  --neg-soft:color-mix(in srgb,var(--red) 12%,var(--white));
  --pos-ink:#2C7A45;
}

.db-main{padding-bottom:var(--s14)}

/* A stage is a step of the demo, not a section of the page. Only one is ever
   shown, and the ask stage is the one that ships open - so with scripting off
   the page is its own pitch and its own form, and nothing below it is a hole
   where content should have been. */
.db-stage{display:none}
.db-stage[data-on="true"]{display:block}


/* ==========================================================================
   01. Ask
   ========================================================================== */
/* Section tier, symmetric, and the white half of this page's alternation:
   db-ask / db-brief (white, and never both on screen) then db-inside (tinted).
   Was --s14 / --s12 - two adjacent steps of the COMPONENT scale used as section
   padding, which is the drift the tier exists to end. */
.db-ask{padding:var(--sec) 0;background:var(--surface)}

/* TWO COLUMNS, AND THE SECOND ONE IS THE ARGUMENT. This fold was a single left
   rail on the site's 1400 wrap, which left about seven hundred pixels of blank
   paper beside it at desktop - on the one page whose pitch is "here, read one"
   and which drew nothing at all until a button was pressed. Narrowing the wrap
   would have closed the gap and spent the opportunity; the gap was not the
   problem, an empty half was.

   1180 rather than the wrap's 1400, so the fold is a measure rather than a
   span, and the copy column caps at 660 for a 60-75 character line. The
   remaining slack sits outside the grid, which is why the section reads as
   centred type rather than as a column pinned left.

   The drawing is second in source order and stacks under the form. */
.db-ask-grid{
  display:grid;grid-template-columns:minmax(0,1fr) 420px;
  /* stretch, not start. Both put the two columns' TOPS on the same line - the
     drawing and the eyebrow share one optical edge either way - but start left
     the card at its content height and the fold ended on a two-hundred-pixel
     rag. Stretch hands the card the column's height and .db-spec-body spends
     it. */
  gap:var(--s14);align-items:stretch;
  max-width:1180px;margin-inline:auto;
}
.db-ask-copy{max-width:660px}

.db-ask .db-lede{
  max-width:58ch;margin-top:var(--s5);
  color:var(--gray);font-size:19px;line-height:30px;
}

.db-form{margin-top:var(--s8)}
/* .db-form-rows is gone with the market select it existed to sit beside
   (2026-08-28). It was `grid-template-columns:1fr 280px`, and leaving it around
   one remaining field would have held a 280px empty column open to the right of
   the input - a gap with nothing in it, which is the usual way a removed field
   leaves a mark. The subject row is a plain .brief-row in the form now. */
.db-form .brief-actions{margin-top:var(--s5)}

/* The try-one row. These are buttons because they act on this page rather than
   navigating anywhere, and they are real buttons so the keyboard gets them. */
.db-try{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin-top:var(--s6)}
.db-try .eyebrow{margin:0 var(--s2) 0 0}

/* ---- the envelope -------------------------------------------------------
   A mail, drawn. The head strip and the signed line are real words; everything
   between them is redacted, for the reason the markup states - a drawing on
   screen before anyone has asked for anything cannot carry mastheads that have
   not agreed to be in it.

   The card is base.css's --e-card on white, and the head strip is the page's
   only tinted ground. Whitespace is doing the emphasis: the drawing is smaller
   than the copy beside it and sits a step below the headline's optical top, so
   it reads as the object being described rather than as a second headline. */
.db-spec{
  margin:0;background:var(--white);
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--e-card);overflow:hidden;
}

.db-spec-head{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:var(--s2) var(--s4);
  padding:var(--s4) var(--s5);
  background:var(--pale);border-bottom:1px solid var(--line);
}
.db-spec-from{
  font-size:12px;line-height:18px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;color:var(--plum);
}
.db-spec-when{font-size:12px;line-height:18px;color:var(--ash);font-variant-numeric:tabular-nums}

/* STRETCHES TO THE COPY BESIDE IT. .db-ask-grid is align-items:start, which is
   right for the card's TOP - the drawing and the eyebrow share one optical line
   - and left its bottom two hundred pixels short of the form, so the fold ended
   on a rag. The card now fills the row and the body takes the slack, which is
   the only part of it that can absorb height without any element changing size.

   The row count did NOT change to close that gap. Six is a morning's brief and
   the same six the lead card on tools.html draws; padding it out to eight would
   be a layout deciding what the product is. What was added is the paragraph,
   which the page's own "what arrives" section says comes first and which the
   drawing had simply been missing. */
.db-spec{display:flex;flex-direction:column}
.db-spec-body{
  display:flex;flex-direction:column;
  padding:var(--s6) var(--s5);flex:1;
}
.db-spec-para{display:grid;gap:8px;margin-bottom:var(--s6)}
.db-spec-para .db-line:nth-child(1){width:100%}
.db-spec-para .db-line:nth-child(2){width:97%}
.db-spec-para .db-line:nth-child(3){width:99%}
.db-spec-para .db-line:nth-child(4){width:58%}

.db-spec-label{
  margin:0 0 var(--s4);
  font-size:12px;line-height:18px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ash);
}

/* One redacted bar, taller and darker than the six below it: the subject line
   of the mail, which is the one line a reader takes in before any item. */
.db-line{display:block;height:8px;border-radius:var(--r-sm);background:var(--mist)}
.db-spec-subj{height:12px;width:82%;background:var(--lavender);margin-bottom:var(--s5)}

/* space-between, so whatever height the card inherits from the column beside it
   is spent on the gaps BETWEEN the six rows rather than pooled as a blank field
   under the last one. A mail pane with a hole in the bottom third reads as a
   drawing that ran out; one with air between its lines reads as a morning that
   is not busy. Capped by max-height on the block so a very tall left column
   cannot pull the rhythm apart - past that the slack goes back to the foot. */
.db-spec-rows{display:flex;flex-direction:column;justify-content:space-between;flex:1;gap:var(--s4);max-height:280px}
.db-spec-row{display:grid;grid-template-columns:3.4rem minmax(0,1fr);gap:var(--s3);align-items:center}
/* Tabular figures so six times sit on one vertical, which is the only reason
   the column reads as a timeline rather than as six loose labels. This is what
   monospace was here for and it is all it was here for - Libre Franklin lines
   its own numerals on request, so the alignment survived the typeface leaving. */
.db-spec-row b{
  color:var(--ash);font-size:13px;line-height:20px;font-weight:500;
  font-variant-numeric:tabular-nums;
}
/* Six widths for six rows, and no two adjacent ones close enough to read as a
   pattern. Same set the lead card on tools.html uses, and for the same reason
   recorded there: a descending set would have drawn a chart of something, and a
   morning's items are not ranked - they are just the morning. */
.db-spec-row:nth-child(1) .db-line{width:100%}
.db-spec-row:nth-child(2) .db-line{width:72%}
.db-spec-row:nth-child(3) .db-line{width:88%}
.db-spec-row:nth-child(4) .db-line{width:64%}
.db-spec-row:nth-child(5) .db-line{width:94%}
.db-spec-row:nth-child(6) .db-line{width:78%}

.db-spec-who{
  padding:var(--s4) var(--s5);
  border-top:1px solid var(--line);background:var(--surface-alt);
  color:var(--gray);font-size:14px;line-height:21px;
}
.db-spec-who b{color:var(--plum);font-weight:600}

/* THE DEFAULT STATE IS THE FINISHED STATE, which is the site's standing rule
   for motion and the reason this is declared the way round it is: the drawing
   above is complete, and the stagger is added only where motion is welcome.
   Nothing is revealed, so with reduced motion nothing is missing. */
@media (prefers-reduced-motion:no-preference){
  @keyframes db-line-in{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}
  .db-spec-subj,.db-spec-para,.db-spec-label,.db-spec-row{
    animation:db-line-in 460ms var(--ease) both;
  }
  /* The mail assembles in the order it is read: subject, paragraph, the label,
     then the six items. Before this the paragraph and the label simply appeared
     while everything around them arrived, which is worse than no motion. */
  .db-spec-para{animation-delay:70ms}
  .db-spec-label{animation-delay:130ms}
  .db-spec-row:nth-child(1){animation-delay:190ms}
  .db-spec-row:nth-child(2){animation-delay:250ms}
  .db-spec-row:nth-child(3){animation-delay:310ms}
  .db-spec-row:nth-child(4){animation-delay:370ms}
  .db-spec-row:nth-child(5){animation-delay:430ms}
  .db-spec-row:nth-child(6){animation-delay:490ms}
}

/* .db-facts is gone. It was a three-item row under the fold and two of the
   three were already said - one of them twice - so it wrapped 2 + 1 and read as
   a broken grid saying nothing new. The markup where it stood records what
   happened to each of the three. */


/* ==========================================================================
   02. Working
   Six lines that arrive one at a time. It is the only honest way to show that
   something is being read rather than fetched, and it is over in eight seconds.
   With reduced motion the whole log lands at once and the stage is a caption.
   ========================================================================== */
/* THE SAME 920 MEASURE THE BRIEF TAKES, and the same left edge. This stage is
   the brief being written, not a different page: held at the site's 1400 wrap it
   started three hundred pixels left of where its own result was about to appear,
   so the log slid sideways at the moment it handed over. Six lines across a
   1352px column also read as a stack of loose labels rather than as one thing
   happening.

   align-content:center as well, because the stage is deliberately taller than
   its contents - it holds the page still for eight seconds - and a short block
   pinned to the top of half a viewport of white reads as a page that finished
   loading badly. */
.db-working{padding:var(--sec) 0;background:var(--surface);min-height:56vh}
/* ON THE ACTIVE STATE, NOT ON THE STAGE. `.db-working{display:grid}` and
   `.db-stage{display:none}` are the same specificity and this sheet declares
   the stage first, so a bare display here won the cascade and left the log on
   screen above the finished brief. Every stage's display belongs to
   [data-on="true"] or to nothing. */
/* CENTRED WITH FLEX, AND THE WRAP IS GIVEN AN EXPLICIT WIDTH, which is the only
   part of this that is not obvious. .wrap carries `margin:0 auto`; in a COLUMN
   flex container those are CROSS-axis margins, and an auto cross margin beats
   align-items:stretch - so the wrap absorbed the free space, shrank to its own
   text and centred itself. The log landed at x=414 instead of the 284 the
   brief's meta line sits on, which is the exact misalignment this rule exists to
   fix. width:100% gives stretch something to stretch, max-width:920 caps it and
   the auto margins go back to doing what they do everywhere else on the site.

   Grid had the same fault for a different reason: its implicit column is
   auto-sized. */
.db-working[data-on="true"]{display:flex;flex-direction:column;justify-content:center}
.db-working > .wrap{max-width:920px;width:100%}
.db-working h2{margin:var(--s3) 0 var(--s8)}

.db-log{list-style:none;padding:0;margin:0;font-size:16px;line-height:2;font-variant-numeric:tabular-nums}
.db-log li{
  display:flex;gap:var(--s3);color:var(--ash);
  opacity:0;transform:translateY(4px);
  transition:opacity 280ms ease,transform 280ms ease,color 280ms ease;
}
.db-log li[data-shown="true"]{opacity:1;transform:none}
.db-log li[data-done="true"]{color:var(--gray)}
.db-log .db-mark{flex:none;width:14px;color:var(--purple)}
.db-log b{color:var(--plum);font-weight:600;font-variant-numeric:tabular-nums}

@keyframes db-blink{0%,55%{opacity:1}56%,100%{opacity:.2}}
.db-log li[data-shown="true"]:not([data-done="true"]) .db-mark{animation:db-blink 1s steps(1) infinite}


/* ==========================================================================
   03. The brief
   A document, not a dashboard. White ground, hairline rules, tabular figures,
   and the only colour that moves is sentiment. Every panel is base.css's own
   .card so this page cannot invent a second one.
   ========================================================================== */
.db-brief{padding:var(--sec) 0;background:var(--surface)}
.db-brief > .wrap{max-width:920px}

.db-brief-top{
  display:flex;flex-wrap:wrap;justify-content:space-between;
  align-items:baseline;gap:var(--s4);
  padding-bottom:var(--s4);border-bottom:2px solid var(--plum);
}
.db-meta{margin:0;font-size:13px;line-height:20px;color:var(--gray);font-variant-numeric:tabular-nums}
.db-meta b{color:var(--plum);font-weight:600}

.db-verdict{
  display:inline-flex;align-items:center;gap:var(--s2);
  margin-top:var(--s6);padding:6px 13px;border-radius:var(--r-pill);
  font-size:12px;line-height:18px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;
}
.db-verdict[data-tone="bad"]{background:var(--neg-soft);color:var(--red)}
.db-verdict[data-tone="good"]{background:var(--pos-soft);color:var(--pos-ink)}
.db-verdict[data-tone="flat"]{background:var(--pale);color:var(--plum)}

.db-brief h2{margin-top:var(--s4)}
.db-write{max-width:66ch;margin-top:var(--s5);color:var(--slate);font-size:19px;line-height:31px}
.db-write mark{background:var(--pale);color:var(--plum);padding:0 3px}

/* The honest empty state. Most brands are this on most days, and a brief that
   invents a narrative out of six trade listings is one you cannot trust on the
   morning there is one. */
.db-quiet{
  margin-top:var(--s6);padding:var(--s5);
  background:var(--haze);border-left:3px solid var(--purple);border-radius:var(--r-sm);
}
.db-quiet h3{font-size:19px;line-height:28px;margin-bottom:var(--s2)}
.db-quiet p{margin:0;max-width:60ch;color:var(--gray);font-size:16px;line-height:25px}

/* The time anchor. It is the whole argument for a daily brief in one line, so
   it gets two rules rather than a box. */
.db-roi{
  margin-top:var(--s6);padding:var(--s3) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  font-size:15px;line-height:23px;color:var(--gray);
  font-variant-numeric:tabular-nums;
}
.db-roi b{color:var(--plum);font-weight:600}

.db-figs{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--s6);margin-top:var(--s8);
}
.db-fig dt{
  font-size:12px;line-height:18px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ash);
}
.db-fig dd{
  margin:var(--s1) 0 0;color:var(--black);
  font-size:34px;font-weight:500;line-height:1.1;
  letter-spacing:-.015em;font-variant-numeric:tabular-nums;
}
/* Direction is not judgement. A rise in coverage is good news on a route
   launch and bad news on a missed filing, so the tone is carried in the data
   and is never inferred from the sign. */
.db-fig .db-delta{margin-left:6px;font-size:14px;font-weight:500;letter-spacing:0;font-variant-numeric:tabular-nums}
.db-delta[data-tone="good"]{color:var(--pos-ink)}
.db-delta[data-tone="bad"]{color:var(--red)}
.db-delta[data-tone="flat"]{color:var(--ash)}

.db-panel{margin-top:var(--s6);padding:var(--s6)}
.db-panel > .eyebrow{margin-bottom:var(--s5)}

.db-bar{display:flex;height:12px;gap:2px;border-radius:var(--r-sm);overflow:hidden}
.db-bar span{display:block}
.db-seg-pos{background:var(--pos)}
.db-seg-neu{background:var(--neu)}
.db-seg-neg{background:var(--neg)}

.db-key{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s6);margin-top:var(--s4);font-size:15px;color:var(--gray)}
.db-key i{display:inline-block;width:9px;height:9px;margin-right:7px;border-radius:2px}
.db-key b{margin-left:6px;color:var(--slate);font-weight:600;font-variant-numeric:tabular-nums}

.db-ranks{display:grid;gap:var(--s4)}
.db-rank{display:grid;grid-template-columns:1fr auto;gap:var(--s1) var(--s4);align-items:baseline;font-size:16px}
.db-rank .db-n{font-size:14px;font-weight:500;color:var(--ash);font-variant-numeric:tabular-nums}
.db-rank .db-track{grid-column:1/-1;height:6px;background:var(--mist);border-radius:3px;overflow:hidden}
.db-rank .db-fill{display:block;height:100%;background:var(--purple);border-radius:3px}
.db-rank .db-fill[data-tone="pos"]{background:var(--pos)}
.db-rank .db-fill[data-tone="neg"]{background:var(--neg)}

.db-voices{display:grid;gap:var(--s5)}
.db-voice{display:grid;grid-template-columns:auto 1fr;gap:2px var(--s4);align-items:center}
.db-face{
  grid-row:span 2;display:grid;place-items:center;
  width:36px;height:36px;border-radius:50%;
  background:var(--pale);color:var(--plum);
  font-size:12px;font-weight:600;letter-spacing:.02em;
}
.db-voice .db-who{font-size:16px;font-weight:500;color:var(--slate)}
.db-voice .db-what{font-size:14px;line-height:21px;color:var(--gray)}

.db-items{
  display:grid;gap:1px;margin-top:var(--s5);
  background:var(--line);border:1px solid var(--line);
  border-radius:var(--r-md);overflow:hidden;
}
.db-item{display:grid;gap:var(--s2);padding:var(--s5) var(--s6);background:var(--white)}
.db-item-top{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  font-size:12px;line-height:18px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ash);
}
.db-item h3{font-size:18px;font-weight:500;line-height:26px;margin:0}
.db-pill{padding:3px 9px;border-radius:var(--r-pill);font-size:11px;font-weight:600;letter-spacing:.14em}
.db-pill[data-tone="pos"]{background:var(--pos-soft);color:var(--pos-ink)}
.db-pill[data-tone="neg"]{background:var(--neg-soft);color:var(--red)}
.db-pill[data-tone="neu"]{background:var(--neu-soft);color:var(--gray)}
.db-keys{display:flex;flex-wrap:wrap;gap:var(--s2)}
.db-key-t{padding:2px 8px;border-radius:var(--r-sm);background:var(--haze);color:var(--gray);font-size:13px;line-height:20px}

.db-acts{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);margin-top:var(--s6)}
.db-copied{background:var(--pale)!important;color:var(--plum)!important}


/* ---- the brief arrives ---------------------------------------------------
   THE HANDOVER, and it is the one transition on this page that has to be one.
   The working log runs for eight seconds and then the whole document replaced
   it in a single frame - a cut, at the exact moment the page is claiming that
   something was WRITTEN. The brief now sets itself down in the order a reader
   takes it: who and when, the verdict, the headline, the paragraph, the time it
   saved, the numbers, then the panels.

   DELAYS BY ELEMENT, NOT BY nth-child. #dbQuiet is empty on every brief but the
   quiet-day one, so a positional stagger spent a step on a box that renders
   nothing and left a hole in the middle of the sequence. Naming them also means
   the order survives a section being added anywhere in that markup.

   IT STOPS AT THE PANELS. Everything below them is off the bottom of any
   viewport this page is read on, so it would finish animating before it could
   be seen - motion nobody watches, paid for on every run.

   The default state is the finished state, as everywhere else on this site: the
   whole sequence lives inside the no-preference query, and .is-in is added by
   js/daily-brief.js only when motion is welcome. */
@media (prefers-reduced-motion:no-preference){
  @keyframes db-rise{
    from{opacity:0;transform:translateY(10px)}
    to{opacity:1;transform:none}
  }

  .db-brief.is-in > .wrap > *{animation:db-rise 480ms var(--ease) both}
  .db-brief.is-in .db-brief-top{animation-delay:0ms}
  .db-brief.is-in .db-verdict{animation-delay:60ms}
  .db-brief.is-in #dbHeadline{animation-delay:110ms}
  .db-brief.is-in .db-write,
  .db-brief.is-in #dbQuiet{animation-delay:165ms}
  .db-brief.is-in .db-roi{animation-delay:215ms}
  /* 260ms, and js/daily-brief.js starts the count on the same number. The
     figures fade in while they are counting rather than after it. */
  .db-brief.is-in .db-figs{animation-delay:260ms}
  .db-brief.is-in .db-panel{animation-delay:320ms}

  /* Below the fold on every viewport this is read on. */
  .db-brief.is-in .db-acts,
  .db-brief.is-in .db-hand,
  .db-brief.is-in .db-note,
  .db-brief.is-in > .wrap > section:not(.db-panel):not(.db-hand){animation:none}
}


/* ==========================================================================
   04. The handoff
   NOT A SECOND EMAIL CAPTURE. tools.html already owns the one form that starts
   a tool, and a page reached from that page collecting an address of its own
   would be two captures for one action. This closes on the thing the specimen
   cannot show - the person who reads it - and sends the visitor to that form
   with the tool and the market already answered.
   ========================================================================== */
/* CENTRED, like every other closer on this site. The temptation was to align it
   left with the document above it, and that is the wrong instinct: the closer is
   the site's own component and it is centred on index, insights and tools, so a
   fourth one that is not would read as a different page rather than as this
   page's ending. Only the route line keeps its own left alignment, because a
   mark beside two lines of text is a row and rows are not centred internally.

   --sec-lg of the section's own padding is already above this, so the margin
   here is only what separates it from the specimen. */
/* NOT A SECTION, despite carrying .closer for its type and its box. It is a
   handoff nested INSIDE .db-brief, so base.css's .closer rule - which now gives
   every real closer --sec-lg block padding and the tinted surface - has to be
   undone here. Measured before this rule: 119.6px of section padding and a
   --surface-alt band wrapped around a card that already sits on a white stage,
   i.e. the section tier applied to something that is not a section. The gate
   below keeps its own white/border/shadow and is unaffected. */
.db-hand{margin-top:var(--s6);padding:0;background:transparent}

/* Was style="margin-top:32px" inline in daily-brief.html - a raw pixel value in
   the markup, off the scale and invisible to any audit of this sheet. 32px is
   --s8. */
.db-items-h{margin-top:var(--s8)}

/* THE BOX IS A GATE, WHICH IS THE ONE THING NO OTHER CLOSER ON THIS SITE IS.
   base.css's .closer-box paints nothing and pads nothing, because .closer is
   itself the tinted half of the section alternation and two nested surfaces
   carrying one message is what that note in base.css retired. This one paints,
   and the reason is that it has something BEHIND it: a gate needs an edge, or
   the blur reads as the page going soft rather than as content withheld.

   WHITE, AND NOT A CHOICE. base.css states the rule at the surface tokens - a
   panel on --surface takes --haze, a panel on --surface-alt takes --white - and
   .closer is --surface-alt. The card, its peek and the gradient it dissolves
   into are therefore all --white, which is also what makes the fade possible:
   a fade has to land on the panel's own ground, not on the band behind it.

   overflow:hidden is load-bearing twice over. It clips the blur to the radius,
   and it is what lets the peek be a window onto something taller than the box.
   The peek is in normal flow with a fixed height, NOT an absolute overlay: an
   overlay has to be told how tall its own parent is at every width, and gets it
   wrong at exactly the widths nobody screenshots.

   NO BORDER. It used to carry border:1px solid --line on top of --e-card, and
   at 880px wide that hairline was the only edge you could actually see - the
   12px card shadow reached about a finger's width under the bottom and nothing
   at all down the sides. The result was a drawn rectangle with a smudge under
   it. --e-panel folds the edge INTO the elevation as a 1px ring at 6% ink, so
   one system draws both, and the ring is the same shade as the shadow instead
   of a flat grey sitting in front of it. See the token in base.css for why the
   card ladder could not just be turned up. */
.db-gate{
  position:relative;overflow:hidden;
  background:var(--surface);border:0;
  border-radius:var(--r-lg);box-shadow:var(--e-panel);padding:0;
}

/* ---- the withheld sheet ----
   --surface, not --surface-alt. It was the tint, which is the same value the
   band behind the card carries, so the card's top edge dissolved into the band
   and the gate read as a grey stripe that had wandered in from somewhere. */
.db-gate-peek{
  position:relative;
  height:340px;overflow:hidden;
  background:var(--surface);
  user-select:none;pointer-events:none;
}
/* scale, not inset. A blurred child stops short of its own clip edge and leaves
   a soft grey halo down both sides of the card; pushing it 6% past the box puts
   that halo outside the crop. transform-origin is the top because the sheet is
   read from its top edge. */
/* Tuned so the metric row lands INSIDE the deepest part of the fade rather
   than below the crop. A sheet whose last visible element is a full-strength
   bar reads as a picture that was cut off; one whose last element is already
   dissolving reads as a page that continues. */
.db-gate-sheet{
  display:grid;gap:var(--s2);
  padding:var(--s6) var(--s8) 0;
  filter:blur(4px);opacity:.8;
  transform:scale(1.06);transform-origin:top center;
}
.db-gate-pill{display:block;width:104px;height:20px;border-radius:var(--r-pill);background:var(--lavender)}
.db-gate-head{height:18px;width:88%;background:var(--ash);opacity:.5;margin-top:var(--s2)}
.db-gate-head.is-short{width:54%}
.db-gate-para{display:grid;gap:8px;margin-top:var(--s3)}
.db-gate-para .db-line:nth-child(1){width:100%}
.db-gate-para .db-line:nth-child(2){width:96%}
.db-gate-para .db-line:nth-child(3){width:99%}
.db-gate-para .db-line:nth-child(4){width:61%}
.db-gate-figs{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s4);margin-top:var(--s4)}
.db-gate-fig{display:block;height:38px;border-radius:var(--r-sm);background:var(--mist)}

.db-gate-ranks{display:grid;gap:var(--s3);margin-top:var(--s5)}
.db-gate-rank{display:grid;gap:6px}
.db-gate-rank i{display:block;height:6px;border-radius:3px;background:var(--mist)}
.db-gate-rank:nth-child(1) .db-line{width:44%}
.db-gate-rank:nth-child(1) i{width:82%;background:var(--lavender)}
.db-gate-rank:nth-child(2) .db-line{width:57%}
.db-gate-rank:nth-child(2) i{width:61%;background:var(--lavender)}
.db-gate-rank:nth-child(3) .db-line{width:38%}
.db-gate-rank:nth-child(3) i{width:39%;background:var(--lavender)}

/* The dissolve. It has to reach solid --white well before the bottom of the
   peek, or the eyebrow below starts on a grey that is not quite the card. */
.db-gate-peek::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(to bottom,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.06) 44%,
    rgba(255,255,255,.42) 66%,
    rgba(255,255,255,.86) 84%,
    rgba(255,255,255,.98) 95%,
    var(--surface) 100%);
}

/* ---- the face ----
   Pulled up into the fade so the copy begins ON the withheld sheet rather than
   under it. That overlap is the whole difference between a gate and a
   decorative strip above a box. */
/* text-align as well as justify-items. base.css centres closer copy through
   `.closer .wrap`, and this closer has no .wrap of its own - it sits inside the
   brief document's one wrap - so the deck was centring its box and left-aligning
   its lines inside it. */
.db-gate-face{
  position:relative;text-align:center;
  display:grid;gap:var(--s5);justify-items:center;
  margin-top:calc(var(--s10) * -1);
  padding:0 var(--s8) var(--s12);
}
.db-gate-face .eyebrow{margin:0;color:var(--plum)}
/* .closer h2 is capped at 16ch, which is right for the four-word headlines the
   other closers carry and wrong for this one - it broke a fourteen-word line
   into four. The cap is widened rather than removed, so it still wraps. */
.db-gate-face h2{max-width:26ch;margin:0}
.db-gate-face .closer-p{margin:0}

/* THE SIGNATURE LINE. --haze, no border, and that is base.css's own rule rather
   than taste: a panel on --surface takes --haze, and the gate card is --surface.
   It had a hairline on white, which is a box drawn around something that is
   already inside a box.

   CAPPED AT 48ch, WHICH IS .closer-p's OWN CAP. It ran the full width of the
   card, which put the fallback sentence on a ~95-character line directly under a
   deck capped at 48ch - the one block of copy on the page set wider than the
   paragraph above it. Same cap, same font size, so the two now share one measure
   and one left and right edge.

   AND ch IS NOT A CHARACTER. It is the advance of "0", which in Libre Franklin
   is about .69em - so 48ch at 18px is ~594px and lands at roughly 79 rendered
   characters, not 48. Worth knowing before anyone "corrects" this number: the
   first attempt here was 58ch on the assumption it meant 58 characters, and it
   rendered 95.

   With a market picked the content is a mark and two short lines and it shrinks
   well inside the cap on its own.

   NO FILL, NO PADDING. tools.css gives .tl-route a white fill and a 16px radius
   because there it sits on the request form's --mist box and has to separate
   from it. Here it sits on the gate, which is already white, so the --haze it
   carried was a tinted card wedged inside a card - the same nesting the tools
   wall dropped, surviving only because it lives in a different stylesheet.

   A mark, a name and a line of text are already a row. They do not need a
   container to be read as a group, and the container was the only thing making
   the closer look like it had a second surface in it. Padding goes with the
   fill: an inset with nothing to inset from is an invisible box you can still
   see the shape of - the same sentence .tl-plate has in tools.css, for the same
   reason. */
.db-hand .tl-route{
  margin:0;border:0;background:none;
  max-width:48ch;padding:0;
}
/* tools.css already sets .tl-route to text-align:left, which is right for the
   named state - a mark beside two lines is a row, and rows are not centred
   internally. Only the fallback paragraph centres, and it is the one element
   that exists in that state alone, so this needs no :has() and no state class. */
.db-hand .tl-route-t{text-align:center}

/* TWO PILLS, NOT A PILL AND A TEXT LINK. The second action was .link, which put
   the page's one alternative route at the weight of a footnote beside a filled
   button.

   IT IS .btn-neutral, AND THAT IS SETTLED - do not "correct" it to secondary.
   base.css has two rules that both reach this button and they pull opposite
   ways: navigation and external links take NEUTRAL, and secondary is the quiet
   companion to a purple primary standing in the same row. This button is
   navigation - it goes to tools.html - so neutral is the rule that governs, and
   the client asked for black directly after seeing the lavender. The row still
   reads correctly because purple is doing the work colour is for here: it is
   the only action on the page that starts a relationship with the network, and
   it is the only purple thing in the card.

   --s3, not --s5. Two buttons are a pair and read as one control at a gap the
   eye can span; --s5 was the spacing for a button and a piece of text. */
.db-hand-acts{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--s3)}

/* NO BORDER, AND --haze RATHER THAN --surface-alt. The dashed keyline was doing
   the job the ground is for, and it was the only dashed edge on the site. The
   token is the rule at base.css's surface pair - a panel on --surface takes
   --haze - and this note sits on the white brief stage; --surface-alt is the
   value for a SECTION that alternates, which at 1.02:1 against white was too
   faint to hold an edge on its own, which is presumably why the border was
   there.

   --r-md, not --r-sm. base.css states the radius rule at the token: --r-lg
   wraps full cards, --r-md compact rows. A two-line note padded 16/20 is a row. */
.db-note{
  margin-top:var(--s10);padding:var(--s4) var(--s5);
  border:0;border-radius:var(--r-md);
  background:var(--haze);color:var(--gray);font-size:14px;line-height:22px;
}
.db-note b{color:var(--slate);font-weight:600}


/* ==========================================================================
   05. What is in one - real markup, and the part a crawler reads
   ========================================================================== */
/* NO RULE ON TOP. --offwhite against --white is 1.02:1, which is the same
   separation .tl-pane already relies on in tools.css and the site's standing
   answer to "how does a box exist without a line". The border and the tint were
   both drawing the same edge, and the border was the louder of the two on the
   one band that is not a card. */
/* The tinted half. Through the surface token, not --offwhite directly, so
   re-toning the alternation re-tones this band with it. */
.db-inside{padding:var(--sec) 0;background:var(--surface-alt)}
/* CAPPED ON THE CONTENT, NOT ON THE WRAP, and that is the whole reason this is
   an inner box rather than a max-width on .wrap. The wrap carries 24px of side
   padding INSIDE its cap, so capping the wrap at 1180 puts its content edge at
   1180 + padding and this heading landed 24px to the right of the H1 above it -
   a misalignment small enough to read as a wobble rather than as a decision.
   .db-ask-grid takes the same measure the same way, so the two sections share
   one left edge down the page. */
.db-inside-box{max-width:1180px;margin-inline:auto}
.db-inside-deck{margin-top:var(--s3);color:var(--gray);font-size:18px;line-height:27px}
.db-inside-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s8);margin-top:var(--s8)}
/* 66ch on the answers, as .bp-faq p and .disclaimer. Three columns give these
   a measure for free; the single-column arrangement below 1023 does not, and
   measured at 834 they ran to 98 characters. */
.db-inside-grid p{max-width:66ch}
.db-inside h3{font-size:20px;line-height:28px;margin-bottom:var(--s2)}
.db-inside p{margin:0;color:var(--gray);font-size:16px;line-height:25px}


/* ==========================================================================
   06. Responsive
   ========================================================================== */
/* THE FOLD COLLAPSES AT 1024, NOT AT THE SITE'S 900. Held to 900 the grid
   spends the last tablet step squeezing a 660px copy column into 500 while the
   drawing keeps its full 420 - the column that has to hold a headline, a deck
   and two fields loses the width, and the one holding six bars does not. It
   goes to one column while both halves are still comfortable, and the drawing
   lands under the form where it caps at the copy measure. */
/* 1023, not 1024, to land on base.css's own tablet boundary. Both were
   max-width, so at exactly 1024px - iPad landscape, and the single most common
   tablet width there is - base.css had already switched this page to its
   DESKTOP layout while this sheet was still serving its tablet one. A 1px band
   of half-collapsed page, on a real device width. */
@media (max-width:1023px){
  .db-ask-grid{grid-template-columns:minmax(0,1fr);gap:var(--s10)}
  .db-ask-copy{max-width:none}
  .db-spec{max-width:520px}
}
@media (max-width:900px){
  .db-inside-grid{grid-template-columns:1fr;gap:var(--s6)}
  .db-lede{font-size:18px;line-height:28px}
}
@media (max-width:600px){
  /* The peek loses a third of its height and the sheet loses its metric row,
     because at 360 the four blocks are 60px wide and read as a grid of nothing
     rather than as figures held back. */
  .db-gate-peek{height:230px}
  .db-gate-sheet{padding:var(--s6) var(--s6) 0}
  /* The four blocks are 60px wide at 360 and read as a grid of nothing rather
     than as figures held back; the rank rows survive because a short bar in a
     narrow column still reads as a bar. */
  .db-gate-figs{display:none}
  .db-gate-face{padding:0 var(--s5) var(--s10);margin-top:calc(var(--s8) * -1)}
  .db-figs{grid-template-columns:repeat(2,1fr);gap:var(--s5)}
  .db-fig dd{font-size:28px}
  .db-item{padding:var(--s4) var(--s5)}
  .db-panel{padding:var(--s5)}
}


/* ==========================================================================
   07. Reduced motion
   The site's standing contract. Nothing here reveals content, so removing the
   motion removes nothing: the log still lands, it just lands at once.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .db-log li{transition:none}
  .db-log .db-mark{animation:none!important}
}
