/* ═══════════════════════════════════════════════════════════════════════════
   THE SITE CHROME — the header bar and the footer bar, defined ONCE.

   L249. Before this file there were SIX definitions of the same two bars, and
   they had drifted in colour, size, breakpoint and vocabulary:

     1  style.generated.css   .hdr family, 40→36px mark, the derived values
     2  style_pages.ts        .hdr family again, 40px fixed, no mobile at all
     3  style.ts              .brand/.mark/.wordmark at 26px/16px — DEAD, no
                              markup has emitted .brand since L220, and its
                              .h-in/.h-up were being overridden by copy 2
                              anyway because STYLE_PAGES concatenates last
     4  legal.css             .site-head/.site-head-inner/.mark/.wordmark
     5  index.html            .hdr/.hlogo/.mk, its own 30px padding
     6  delete_request.ts     copy 4's markup, in TypeScript

   Q22 established the blocker everyone had been repeating — "a static asset
   cannot import a TypeScript constant" — is true of MARKUP and false of CSS.
   delete_request.ts had been proving it since L088: TypeScript that <link>s a
   static stylesheet. So the CSS unifies here and the markup stays four copies
   speaking one vocabulary.

   ── WHO USES THIS FILE ──
   · privacy.html, terms.html, support.html, delete-account.html — <link>
   · delete_request.ts (the three POST outcome pages) — <link>, via legal.css
   · layout.ts — INLINED at build time, not linked. See below.
   · index.html — <link>, emitted by tools/derive_home.mjs

   ── WHY layout.ts INLINES AND THE OTHERS LINK ──
   L011: a guest page fetches no off-origin subresource, after a blocked font
   CDN once left a page inert. A same-origin <link> is not off-origin and does
   not carry that risk — but it is still a round trip that blocks first paint,
   and the guest pages are the ones that most need to render immediately: they
   are opened from a chat app's in-app browser, on a phone, on a stranger's
   connection, and the page's whole job is to look like it came from a real
   app. The legal pages are read, not glanced at, and already pay for
   legal.css; one more same-origin request costs them nothing they were not
   already spending.

   So: the file is the single source, and layout.ts imports it as text through
   the wrangler "Text" rule (wrangler.jsonc:11) that style_spec.ts already uses
   for style.generated.css. One definition, two delivery mechanisms, no copy.

   ═══════════════ THE CHROME BOUNDARY, AND IT IS A JUDGEMENT ═══════════════

   Nobody had drawn this line before, so here it is explicitly.

   IN — the two bars, and everything that is the same on every page of the
   site regardless of what the page is:
     .hdr .hdr-in .hdr-h .hdr-ic  .hdr b  .h-in .h-up .lg
     .ftr .ftr-in .flinks .flinks a  .fc
   plus their one breakpoint.

   OUT — anything a page owns:
     · THE CONTAINER WIDTH. The guest pages cap at 1080, the legal pages at
       720, the homepage at 940. Those differ for real reasons — a prose
       document wants a narrower measure than a two-column event page — and
       collapsing them would be a design change wearing a refactor's clothes.
       The bars are full-bleed, so they do not need to know.
     · the pitch card and the app card. They sit near the footer and are not
       the footer; they appear on some routes and not others, which is the
       test.
     · page background, type scale, prose styling, everything below the header
       and above the footer.

   The test that produced that line: does it look identical on a privacy page
   and on an event page? If yes it is chrome. If it legitimately differs, it
   belongs to the page. The container width fails that test and the mark
   passes it.

   ── VALUES ──
   These are the DERIVED sheet's, verbatim — style.generated.css was the copy
   with the mobile treatment and the most route shapes behind it (~20 against
   4 and 1), so it wins the vocabulary and the numbers. The reasoning behind
   each number stays in style_prod.css where it was written; it is not
   repeated here.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── header ────────────────────────────────────────────────────────────── */

/* Transparent and full-bleed. L220 D2 / L223 D3 — the header was capped at the
   body's 1080 and centred, so at 2560 the mark sat 768px in with 740px of
   empty bar beside it. The BODY still caps; only the bars run edge to edge. */
/* L250 — THE BARS SET THEIR OWN LINE-HEIGHT, and this was found by the diff
   rather than reasoned out. legal.css's body says `line-height:1.6` and the
   guest sheet's says nothing, so the same header measured 60px on one family
   and 58px on another purely by inheritance: chrome.css declared every box
   property and then let the page decide how tall the text inside them was.
   A shared bar that inherits its own height is not shared. `normal` is what
   the guest pages were already getting, so this changes nothing there. */
.hdr,.ftr{line-height:normal}
.hdr{background:transparent}
.hdr-in{padding:14px 22px 4px;display:flex;align-items:center;gap:11px}

/* L220 D3 — the mark and the wordmark are ONE link home. flex:1 lives here
   rather than on .hdr b so the anchor, not the word, does the pushing. */
/* L270 — color:inherit joins text-decoration:none, and for the same class of
   reason. The homepage's wordmark was a <span> until now (see derive_home's T6
   list); as an <a> with no colour rule it took the UA stylesheet's LINK BLUE —
   measured at rgb(0, 0, 238) against rgb(167, 159, 255) on the static family.
   .hdr b paints the word itself so the blue was not visible, which is exactly
   why it needed measuring rather than looking.

   inherit, not a token: this element holds no text of its own — the mark is a
   masked background and the wordmark is the <b> inside — so it should take
   whatever the page is using rather than assert a colour it never paints. */
.hdr-h{display:flex;align-items:center;gap:11px;flex:1;min-width:0;
  text-decoration:none;color:inherit}

/* ── THE MARK, AND IT IS NOW FLAT ──
   L249 D3. mark-120.png is a GRADIENT: of its 2934 opaque pixels, zero are
   #6C63FF. It runs #5A3BEF → #916EFF, mean #7555F8 — measurably more
   saturated than the wordmark sitting 11px to its right, which is a flat
   var(--primary). They have never matched, on any page, since the PNG shipped.

   This is a CSS mask over the token, not an <img>. The colour comes from
   --primary, so the mark CANNOT drift from the wordmark again — neither one
   holds a colour of its own any more. An <img> could not do this: the fill
   would live in the file and be back to two sources of truth.

   WHAT IT MASKS IS THE REAL APP ICON. L249 pointed this at a traced SVG of the
   mockup's mark and a test caught it; L250 R1 reversed that, because L139's
   ruling holds — a redrawn glyph is a DIFFERENT MARK from the one on the phone
   the visitor is being asked to install, and a trace is a redrawing however
   careful. /icon/mark-mask.png is emitted by tools/make_header_mark.mjs from
   the SAME keyed buffer as mark-120.png, from appstore.png; that script
   compares the two alpha channels pixel for pixel (14400 px, 0 differing) and
   refuses to write if they diverge. The silhouette is the artwork by
   construction, not by resemblance. A mask reads alpha and discards RGB, so
   the gradient that never matched #6C63FF does not participate.

   L252 — THE URL IS LOAD-BEARING AND IT WAS WRONG ON PROD. This said
   /icon/mark.svg, which L250 deleted; the deployed page masked against a 404,
   and a mask whose source cannot load masks EVERYTHING out, so the header
   rendered no mark at all — not a broken-image glyph, nothing. There is no
   fallback for this and there cannot be one, so the asset and this URL move
   together or the mark disappears silently.

   -webkit- first for Safari, which still wants the prefix on mask-image. */
.hdr-ic{width:40px;height:40px;flex-shrink:0;display:block;
  background-color:var(--primary);
  -webkit-mask:url('/icon/mark-mask.png') center / contain no-repeat;
  mask:url('/icon/mark-mask.png') center / contain no-repeat}

/* L222 D2 — THE BRAND PURPLE, both themes, matching the app's own persistent
   chrome: floating_tab_header.dart:55-62 is an unconditional
   Color(0xFF6C63FF). --primary is #6C63FF in every :root on this site. */
.hdr b{font-size:20px;font-weight:700;color:var(--primary);letter-spacing:-.2px;
  min-width:0}

/* !! INERT !! — see layout.ts's header(): there is no web login and no web
   signup, so these are <span> and not <a>. "An <a> with no href is a link that
   does nothing." They are styled exactly as the controls they will become, and
   docs/built-not-verified.md (tether repo) holds the thing that must not be
   lost when they go live: signing in from an invite has to return you TO that
   invite. L249 gives them to the legal pages too, which never had them. */
/* ── L270 · text-decoration IS DECLARED HERE NOW, AND THAT IS TWO FIXES ────
   These were <span> until L270 and a span needs no decoration rule, so there
   was none. As anchors they took the UA stylesheet's underline — and only on
   two of the four families, because legal.css has no anchor reset and
   style_prod.css's [PROD-2] does. Measured: .h-in read `deco=underline` on the
   static pages and the delete_request outcome pages, `deco=none` on the guest
   pages and the homepage.

   chrome_diff PASSED THAT, and the reason is worth more than the fix. Its
   PROPS list is DERIVED from the properties chrome.css declares (line 118), so
   a property this file never mentioned was never compared. That is the second
   of the four documented blind spots — inherited-versus-declared — arriving in
   its sharpest form: the divergence appeared precisely BECAUSE an element's
   TAG changed, which is the one thing a property-by-property diff of declared
   values cannot see.

   So declaring it here does two things. It stops the underline, and it puts
   text-decoration-line into PROPS, which means chrome_diff compares it across
   all four families from now on. The gate widens by the same edit that closes
   the hole. */
.h-in{font-size:13px;font-weight:650;color:var(--on-surface);padding:7px 13px;
  border-radius:99px;white-space:nowrap;text-decoration:none}
.h-up{font-size:13px;font-weight:700;color:#fff;padding:7px 14px;
  border-radius:99px;background:var(--primary);white-space:nowrap;
  text-decoration:none}

/* "Create an account" on a laptop, "Create account" on a phone. Both ship and
   CSS picks — there is no JavaScript to choose with. */
.lg{display:inline}

/* ══ W25 · THE APP LINK ═══════════════════════════════════════════════════
   The signed-in header's way into /app/. It rides on .h-in for the pill, so it
   inherits the <899 tightening [HEADER-4] measured; these rules only swap the
   label for a glyph. Both ship and CSS picks — the same mechanism as .lg
   above, and for the same reason: there is no JavaScript here to choose with.

   THE GLYPH'S GEOMETRY IS DECLARED, NOT INHERITED. style.ts has a global
   `svg{fill:none;stroke:currentColor;width:16px;…}` that would size this — but
   it lives in the MAIN sheet, and layout() ships STYLE_SPEC instead on every
   page that can draw a signed-in header (`spec = auth || right || width`).
   chrome.css is inlined on all four families, so the glyph states its own size,
   stroke and fill here and renders identically everywhere, rather than
   depending on which family happened to carry the global rule. */
.h-app{display:inline-flex;align-items:center}
.h-app-i{display:none}

/* ── footer ────────────────────────────────────────────────────────────── */

/* L221 R2 — full bleed, matching .hdr-in, so the footer is not the only chrome
   still floating in a column once the header went edge to edge. */
.ftr{margin-top:30px;background:var(--surface);
  border-top:1px solid var(--border)}
.ftr-in{padding:16px 28px;display:flex;align-items:center;gap:18px;
  flex-wrap:wrap}
.flinks{display:flex;gap:16px;flex:1;flex-wrap:wrap}
/* .ftr .flinks a, NOT .flinks a, and the extra class is load-bearing.
   [PROD-2] in the guest sheet is `a,a:link,a:visited,…{color:inherit}` — and
   `a:link` is (0,1,1), exactly the same specificity as `.flinks a`. chrome.css
   is inlined FIRST, so on the guest pages the reset came later and won: the
   footer links were rendering --on-surface instead of --on-surface-variant.
   The chrome diff caught it. Third time this pseudo-class specificity trap has
   fired (L245's a.b1, L247's a.b, now this), and the fix is the same each
   time: outrank the reset rather than hope to be later than it. */
.ftr .flinks a{font-size:12px;color:var(--on-surface-variant);
  text-decoration:none}
/* margin-top:0 is not padding — it is the same lesson as line-height above.
   .fc is a <p>, and legal.css says `p{margin-top:12px}`, so the copyright sat
   12px lower on the legal family than on the guest pages. A shared bar that
   lets the page decide its internal spacing is not shared. The mobile block
   below sets 9px deliberately, and still does. */
.fc{font-size:11.5px;color:var(--on-surface-variant);opacity:.6;margin-top:0}

/* ── L267 R1 · THE LANGUAGE SELECTOR ──────────────────────────────────────
   A DECLARED DIFFERENCE BETWEEN THE FAMILIES, not drift. .flang is emitted by
   layout.ts's footer() only — the server-rendered families — and never by the
   four static .html files, because those are lang="en" single files with no
   translation to switch to. chrome_diff knows this rule by name; see its
   DECLARED list. The STYLE lives here anyway so that the day the legal pages
   move into the Worker, the markup is the only thing that has to change.

   F51 — IT IS A DISCLOSURE NOW, not a flat row. Seven names side by side wrapped
   across the footer on a phone and did not read as a control; the summary shows
   the current language and opening reveals the other six. <details> is the only
   native disclosure that needs no JavaScript, which is the same constraint that
   made this seven links rather than a <select> in the first place.

   The type is still the footer's — 12px, --on-surface-variant — so it sits with
   .flinks rather than beside them. What it no longer inherits is the flat row's
   opacity trick: the current locale used to read at full opacity against dimmed
   siblings, and with the siblings behind a disclosure there is nothing to be
   contrasted against. The summary carries the weight instead. */
.flang{position:relative}
/* F51 — the summary IS the control, so it has to look like one. Everything
   else in this bar is a bare link; this is the only thing that opens. The
   hairline and the radius are what say so at a glance, and both are the
   footer's own tokens rather than new values. */
.flang summary{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  font-size:12px;font-weight:650;color:var(--on-surface-variant);
  padding:4px 9px;border:1px solid var(--border);border-radius:999px;
  list-style:none;user-select:none}
/* Both spellings: the ::marker one is standard, the WebKit pseudo-element is
   what Safari still reads. Neither alone removes the triangle everywhere. */
.flang summary::-webkit-details-marker{display:none}
.flang summary::marker{content:''}
/* Our own chevron, drawn in CSS rather than taken from the sprite: chrome.css
   is inlined on all four families and the static ones carry no sprite, so a
   <use> here would be a broken reference on three of them. It rotates on open,
   which is the only state change the control has. */
.flang summary::after{content:'';width:5px;height:5px;margin-top:-2px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg);opacity:.7}
.flang details[open] summary::after{transform:rotate(-135deg);margin-top:2px}
.flang summary:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
/* UPWARDS, and absolutely: this sits at the bottom of the page, so a list that
   pushed the footer taller would move the control out from under the finger
   that just tapped it. */
.flang-list{position:absolute;bottom:calc(100% + 6px);left:0;z-index:5;
  display:flex;flex-direction:column;gap:2px;padding:6px;
  background:var(--surface);border:1px solid var(--border);border-radius:12px;
  box-shadow:0 6px 20px rgba(0,0,0,.18);min-width:132px}
.flang-list a{font-size:12px;color:var(--on-surface-variant);text-decoration:none;
  padding:6px 9px;border-radius:8px;white-space:nowrap}
.flang-list a:hover,.flang-list a:focus-visible{background:var(--surface-highest);
  color:var(--on-surface)}

/* ── the one breakpoint ────────────────────────────────────────────────── */

/* L249 D4 — 899px, everywhere. The derived sheet already used it (nine times);
   index.html adopted it at L245; the legal family had no chrome breakpoint at
   all and its 480px rule stays for the prose it was written for.
   ONE number for the chrome, on every page of the site. */
@media (max-width:899px){
  .hdr-in{padding:12px 14px 2px;gap:9px}
  .hdr-ic{width:36px;height:36px}
  /* L249 D3 — SIGN IN SHOWS ON MOBILE. index.html hid it below 899 and the
     guest pages never did; the guest pages were right. What shortens is the
     word "an", not the control. */
  .h-up .lg{display:none}
  /* ══════════════════════════════════════════════════════════════════════
     [HEADER-4] · THE HEADER CARRIES FOUR THINGS. ALL FOUR. ALWAYS.

     THE HEADER CARRIES FOUR THINGS ON EVERY PAGE, AT EVERY WIDTH, IN EVERY
     LOCALE: the mark, the wordmark "Atsuma", Sign in, and Create an account.

     THIS IS A FIXED REQUIREMENT. IT IS NOT A TRADE-OFF TO BE RESOLVED AGAINST
     SPACE. Removing any of the four is not a layout decision and is not a
     lever. If they do not fit, the strings, the type, the padding or the mark
     give — not the count.

     ── WHY THIS IS WRITTEN HERE, IN THESE WORDS ──────────────────────────
     It kept getting partially implemented, three times, each time by someone
     who believed they were making a reasonable call:

       L245  hid Sign in on the homepage
       L266  hid Sign in everywhere below 899 (and this comment, then called
             [I18N-1], is the one that made it read as negotiable — it framed
             the choice as "which one can go" and answered it)
       and before both, [I18N-1] hid the WORDMARK below 899

     Every one of those was a real overflow met with a deletion. The overflow
     was never the problem; treating the four as optional was.

     ── HOW IT FITS AT 360, MEASURED ──────────────────────────────────────
     L274. Per item, rendered width / max-content, all four visible, at 360px
     (332px of usable width after .hdr-in padding, three 9px gaps):

       BEFORE — the four with the old strings and the old control style
         loc  mark  word  Sign in  Create   need/avail
         en    36    60     69      125      317/332  fits
         de    36    60     90      124      337/332  OVER by 5
         es    36    60    110      137      370/332  OVER by 38
         fr    36    60    110      134      367/332  OVER by 35
         ja    36    60     77      132      332/332  at the limit
         ko    36    60     60       87      270/332  fits
         pt    36    60     64      129      316/332  fits

       AFTER — two levers, no deletions
         en    36    60     60      127      310/332  fits
         de    36    60     80       91      294/332  fits
         fr    36    60     83       76      282/332  fits
         es    36    60     55       87      265/332  fits
         ja    36    60     67      104      294/332  fits
         ko    36    60     51       75      249/332  fits
         pt    36    60     55       85      263/332  fits

     LEVER 1 — SHORTER STRINGS in the long locales. Changing a translation is
     not changing the requirement. de "Konto erstellen" -> "Registrieren";
     fr "Se connecter"/"Créer un compte" -> "Connexion"/"S'inscrire";
     es "Iniciar sesión"/"Crear una cuenta" -> "Entrar"/"Registrarse";
     ja dropped the particle; pt "Criar uma conta" -> "Criar conta". They live
     in tether's ARB files and reach here through tools/export_web_strings.dart.

     LEVER 2 — TIGHTER CONTROLS below 899 only: 12px type and 6px/10px padding
     instead of 13px and 7px/13-14px. See the rules under this comment.

     TWO LEVERS WERE NOT NEEDED and are named so the next person knows the
     headroom: the mark does NOT shrink below its 36px (a 32px mark buys
     another 4px), and the controls do NOT stack onto a second row. The worst
     case after the change is en at 310 of 332 — 22px spare.
     ══════════════════════════════════════════════════════════════════════ */
  .h-in,.h-up{font-size:12px;padding:6px 10px}
  /* W25 — LEVER 1, THE STRING GIVES. The label costs 54-98px depending on
     locale and the header has nothing like that spare: measured, the labelled
     pill spilled the wordmark in six of seven locales at 360. So below 899 the
     words go and the glyph stays. THE CONTROL DOES NOT GO — that is the one
     move [HEADER-4] forbids, and it would have failed precisely where it
     matters most, since an invite is opened on a phone far more often than on
     a laptop. The accessible name is the localised label, on the anchor. */
  .h-app-t{display:none}
  .h-app-i{display:block;width:18px;height:18px;
    fill:none;stroke:currentColor;stroke-width:2;
    stroke-linecap:round;stroke-linejoin:round}
  .h-app{padding:6px 9px}
  .ftr-in{padding:16px;display:block}
  .fc{margin-top:9px}
  .flinks{margin-top:14px}
  .flang{margin-top:12px}
}
