/* ──────────────────────────────────────────────────────────────────
   HumanFriend.Club — marketing site

   Tracks the app rather than DESIGN.md alone: where the two differ,
   the app's current build wins, because the site is its shop window.
   Each such case is commented where it occurs. Sources:
     mobile/src/global.css        palette + type tokens
     mobile/src/constants/theme.ts bevels, member and option fills
     mobile/src/components/*      the component recipes
   ────────────────────────────────────────────────────────────────── */

/* ── faces ──────────────────────────────────────────────────────────
   Self-hosted from mobile/assets/fonts, converted to woff2. Commit
   Mono and Manifont Grotesk are both SIL OFL 1.1 (licences ship
   alongside them in this folder), which permits web embedding.
   TAY Big Bird is deliberately absent — see web/README.md. */

@font-face{
  font-family: "Commit Mono";
  src: url("fonts/CommitMono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Commit Mono";
  src: url("fonts/CommitMono-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Manifont Grotesk";
  src: url("fonts/ManifontGrotesk-Book.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Manifont Grotesk";
  src: url("fonts/ManifontGrotesk-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

:root{
  /* ground */
  --studio:        #E7E7E4;
  --concrete:      #ABA79F;
  --heather:       #8D9093;
  --periwinkle:    #A9B8DD;
  --ink:           #1B2230;
  --page:          #FFFFFF;  /* the app's --background */

  /* derived — darkened for text contrast, do not substitute the originals */
  --row-alt:       #DCE1EC;
  --link:          #2F5B92;
  --link-visited:  #6E4F80;
  --bevel-light:   #F5F5F3;

  /* structure */
  --cornflower:    #4A80C0;
  --cobalt:        #1D87D3;
  --electric:      #0B90EA;

  /* signal — never a background field */
  --crimson:       #BE2019;
  --marigold:      #F8A81E;
  --volt:          #D8F61B;
  --hood-green:    #57EE20;
  --floss-yellow:  #EEE400;

  /* soft — tinted fills only, at low surface area */
  --wig-pink:      #F2A2A9;
  --vinyl-pink:    #F6C4CB;
  --velour-lilac:  #DBB8E3;
  --cream-curl:    #F0E6D3;

  /* derived for text contrast. DESIGN.md §5 sets a 4.5:1 floor and calls
     it non-negotiable; --heather as meta text misses it (3.22:1 on the
     white page). Darkened in the same hue, the way §1 already derives
     --link and --row-alt. Measured on --page: 6.05:1. */
  --meta-text:     #5C6370;

  /* bevels. 3px, not DESIGN.md's 1px: the app raised BEVEL_WIDTH to 3 so
     a control reads as moulded rather than as a hairline rule
     (constants/theme.ts). The site follows the app. */
  --bevel-dark:    #8D9093;
  --bevel-face-pressed: #DCDCD9;
  --bevel-width:   3px;

  --font-mono:    "Commit Mono", ui-monospace, Menlo, Consolas, monospace;
  --font-display: "Manifont Grotesk", "Futura", "Century Gothic", sans-serif;
}

/* ── reset + period rules ───────────────────────────────────────── */

*, *::before, *::after{ box-sizing: border-box; border-radius: 0; }
html{
  -webkit-text-size-adjust: 100%;
  /* Reserve the scrollbar gutter on every page, whether or not it scrolls.
     Without this a short page has no scrollbar and a long one does, the
     content box differs by ~15px between them, and everything centred jumps
     sideways by half that on each navigation. */
  scrollbar-gutter: stable;
}

body{
  margin: 0;
  /* The page is short and the window is not, so main takes the slack and
     centres its content in it; the footer stays at the bottom either way.
     min-height rather than height, so a window shorter than the content
     scrolls normally instead of clipping it. */
  min-height: 100vh;
  display: flex; flex-direction: column;
  background: var(--page);
  color: var(--ink);
  /* Commit Mono carries the whole interface in the app (--font-sans and
     --font-mono both point at it), so it carries the site too. This
     replaces DESIGN.md §3's Verdana stack, which no longer appears
     anywhere in the product. */
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
}

/* Sparkle layer: fixed, not absolute. An absolutely positioned sparkle that
   falls past the fold counts towards the document's scrollable area and pops
   a scrollbar into existence for the frame or two before it is killed. A
   fixed subtree never contributes to scroll size, so the sparkles cannot
   move the page. The script positions them in viewport coordinates to
   match. Over everything, catching no clicks. */
.sparkles{
  position: fixed; top: 0; left: 0;
  width: 0; height: 0;
  pointer-events: none;
  z-index: 9999;
}

/* ── cross-document navigation ──────────────────────────────────────
   The white flash between pages is the browser dropping the old document's
   paint before the new one renders. A view transition holds the old frame
   until the new document is ready, which closes that gap.

   The brandmark is given a name, so the browser treats it as the same
   element on both sides and carries it across rather than repainting it —
   the header genuinely does not redraw, which is what was asked for.

   The animations are then zeroed. The point here is removing the flash,
   not adding motion: DESIGN.md is explicit that there are no transitions
   in this interface, and a cross-fade would be one. Give these a duration
   if a fade is ever wanted. */
@view-transition{ navigation: auto; }

.brandmark{ view-transition-name: brandmark; }

::view-transition-old(root),
::view-transition-new(root),
::view-transition-old(brandmark),
::view-transition-new(brandmark){
  animation: none;
  mix-blend-mode: normal;
}

/* No shadows, no blur, no gradients, no transitions — anywhere. */
*{ box-shadow: none !important; text-shadow: none !important; transition: none !important; }

h1, h2, h3, h4, p, ul, ol, dl, figure, table{ margin: 0; }
ul, ol{ padding: 0; list-style: none; }
img, svg{ max-width: 100%; display: block; }

/* Links are bracketed, never underlined; the underline is reserved for a
   value that can be edited in place (DESIGN.md §3). The brackets are
   drawn here so the markup stays plain text.
   Colour is --link rather than §2's --cobalt: cobalt on the white page is
   3.85:1, under the §5 floor, and --link is the palette's own darkened
   cornflower for exactly this job. */
a{ color: var(--link); text-decoration: none; }
a:visited{ color: var(--link-visited); }
a:hover{ color: var(--crimson); }
a.bracket::before{ content: "["; }
a.bracket::after{ content: "]"; }
a.danger{ color: var(--crimson); }

:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

/* Selected text takes --floss-yellow, which DESIGN.md §1 already earmarks as
   the search-term highlight. --ink is forced on top of it: the default
   selection colour is the browser's, and on the dark button fills the text
   would otherwise stay white on yellow. */
::selection{ background: var(--floss-yellow); color: var(--ink); }

/* ── shell ──────────────────────────────────────────────────────── */

.skip{
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--page); padding: 8px 12px; z-index: 10;
}
.skip:focus{ left: 8px; top: 8px; color: var(--page); }

/* ── nav keys ───────────────────────────────────────────────────────
   The site's navigation is the app's bottom tab bar, moved to the top and
   sat under the masthead (components/bottom-tab-bar.tsx). Each key is the
   page mast in miniature: the same studio face, the same 3px raised
   bevel. The keys butt together with no gap, so one key's dark right edge
   meets the next one's light left edge and reads as a single seam.
   A key is down while it is held and for as long as you are on its page,
   and the two look the same. Three things go with the finger: the face
   darkens, the legend shifts a pixel down-right, and the bevel inverts. */

.tabs{ display: flex; flex-wrap: wrap; margin: 0 -12px; background: var(--page); }
.tabs a{
  flex: 1 1 0; min-width: 118px;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  min-height: 52px; padding: 14px 8px 13px;
  background: var(--studio); color: var(--meta-text);
  font-size: 11px; letter-spacing: .11em; text-transform: uppercase;
  border: var(--bevel-width) solid;
  border-top-color: var(--bevel-light); border-left-color: var(--bevel-light);
  border-bottom-color: var(--bevel-dark); border-right-color: var(--bevel-dark);
}
.tabs a:visited{ color: var(--meta-text); }
.tabs a:hover{ color: var(--ink); }
.tabs a:active,
.tabs a[aria-current="page"]{
  background: var(--bevel-face-pressed); color: var(--ink); font-weight: 700;
  border-top-color: var(--bevel-dark); border-left-color: var(--bevel-dark);
  border-bottom-color: var(--bevel-light); border-right-color: var(--bevel-light);
  /* Asymmetric against a centred legend: two pixels on one side moves the
     middle by one. */
  padding: 15px 6px 12px 10px;
}

.wrap{ max-width: 960px; margin: 0 auto; padding: 0 12px 20px; width: 100%; }
main.wrap{ flex: 1 1 auto; }

/* Every page's contents sit in one thin --ink rectangle. */
.sheet > * + *{ margin-top: 14px; }
.sheet > .rule{ margin: 24px 0; }
/* Prose pages set their body copy on the measure, left-aligned, rather than
   centred like the home page's short lines. */
/* One measure in px, shared. `ch` would resolve against each element's own
   font size, which put the 11px headings on a narrower column than the 13px
   body and left their left edges out of line. */
.sheet{ --measure: 560px; }
/* The sheet is given tabindex="-1" and focused after a page swap, so a
   screen reader lands on the new content. It is a container, not a control:
   Safari draws a ring on a programmatically focused element where Chromium
   does not, which reads as a second border just outside this box's own.
   Nothing is lost by suppressing it — Tab cannot reach a tabindex="-1"
   element, so no keyboard user depends on this ring. */
.sheet:focus, .sheet:focus-visible{ outline: none; }
/* .lede is capped at 62ch, so outside the hero it also needs centring as a
   block — otherwise the text is centred inside a box that is itself sitting
   against the left edge, and the whole thing reads off-centre. */
.sheet > .lede{ margin-inline: auto; }
.sheet .prose{ max-width: var(--measure); margin-inline: auto; text-align: left; }
.sheet h2.section{
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--meta-text); font-weight: 400;
  border-bottom: 1px solid var(--concrete); padding-bottom: 6px;
  max-width: var(--measure); margin-inline: auto;
}
.sheet > h1.display{ margin-bottom: 22px; }
.sheet{
  border: 1px solid var(--ink);
  padding: clamp(18px, 3vw, 34px) clamp(14px, 2.4vw, 28px);
}
.wrap--head{ padding-bottom: 0; }
.stack > * + *{ margin-top: 12px; }

.crumbs{ font-size: 11px; color: var(--meta-text); padding: 8px 0; }
.crumbs .sep{ padding: 0 5px; }
.crumbs strong{ color: var(--ink); font-weight: 700; }

/* ── masthead band ──────────────────────────────────────────────────
   Port of BrandHeader (components/brand-header.tsx): thirteen palette
   slices at the same flex weights, one lowercase Manifont Grotesk Bold
   letter per slice stretched to its width, and the stripe dissolving
   upward through a 4x4 ordered dither. Slice widths and colours must
   stay in step with SLICES there. */

.masthead{
  position: relative;
  display: flex;
  height: 54px;
  margin: 0 -12px;   /* full-bleed past the page gutter, as in the app */
}
.masthead > span{
  position: relative;
  display: flex; align-items: flex-end; justify-content: center;
  padding-bottom: 7px;
  min-width: 0;
}
.masthead svg{ width: 84%; height: 32px; overflow: visible; }
.masthead text{
  font-family: var(--font-display); font-weight: 700; font-size: 100px;
  fill: var(--ink); text-anchor: middle;
}
/* ── panels ─────────────────────────────────────────────────────── */

.panel{ border: 1px solid var(--concrete); background: var(--page); }
.panel__title{
  border-bottom: 1px solid var(--concrete);
  padding: 9px 14px;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--meta-text);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 10px;
}
.panel__title .aside{ margin-left: auto; color: var(--meta-text); }
/* ── hero ───────────────────────────────────────────────────────────
   The whole page in one thin --ink box: mark, wordmark, clock, signup.
   1px, square, no fill of its own — the frame is the only chrome the page
   has now that the masthead and nav keys are gone. */
/* No frame: the clock and the signup sit straight on the page. The box is a
   one-line restore — `border: 1px solid var(--ink)` plus the padding back. */
.hero{
  background: var(--page);
  padding: 0;
  text-align: center;
}
.hero > * + *{ margin-top: 14px; }
.hero .rule{ margin: 20px 0; }

/* The mark and wordmark sit above the box, unboxed, at the top of the page. */
.brandmark{ text-align: center; padding: 22px 0 18px; }

/* "human [lamb] friends" on one line, the lamb standing between the two
   words. In the flow now rather than absolutely placed, so the row's height
   is simply the lamb's and there is no overhang to clear — which is what
   lets the links sit close underneath.

   --lamb-scale is the lamb's height as a multiple of the font size. The
   app uses 4, which is right when the lamb sits behind the words; standing
   between them that reads as a lamb with a caption, so it is 2.15 here.
   It also sets the ceiling on the type, since the row measures
   (6.46 + 1.16 x scale) x font-size + gaps and has to fit the column. */
.wordmark{
  --wordmark: clamp(26px, 7.4vw, 80px);
  --lamb-scale: 2.15;
  --wordmark-drop: 3px;
  display: flex; align-items: center; justify-content: center;
  gap: clamp(1px, 0.45vw, 6px);
  font-size: var(--wordmark);
  margin: 0 0 10px;
}
/* Optical nudge: the words drop 3px against the lamb, which stays put.
   translate rather than a flex alignment change, so it shifts the glyphs
   without touching the row's height or the lamb's position. */
.wordmark span{ transform: translateY(var(--wordmark-drop)); }

.wordmark .lamb{
  height: calc(var(--wordmark) * var(--lamb-scale));
  width: auto; max-width: none; margin: 0; flex: 0 0 auto;
}

/* Bracketed links rather than buttons — the app's link device
   (DESIGN.md §3), drawn by a.bracket's ::before/::after. */
.toplinks{
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  justify-content: center; margin-top: 0;
}
.toplinks a[aria-current="page"]{ color: var(--ink); }
.toplinks a{
  font-size: 12px; letter-spacing: .08em;
  /* Lowercased in CSS rather than in the markup, so the accessible name
     keeps its proper capitalisation — a screen reader still says "Reddit",
     not "reddit". Same device the app uses for its display lines. */
  text-transform: lowercase;
  /* 44px tap target without padding the row out and losing the density. */
  padding: 12px 2px;
}
.panel__body{ padding: 14px; }
.panel__body > * + *{ margin-top: 10px; }

.sr-only{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ── type ───────────────────────────────────────────────────────── */

.display{
  font-family: var(--font-display); font-weight: 400;
  font-size: 34px; line-height: 1.16; letter-spacing: -0.01em;
  text-transform: lowercase;   /* the app sets its display lines lowercase */
}
.lede{ font-size: 13px; line-height: 1.75; max-width: 62ch; }
.meta{ font-size: 11px; line-height: 1.7; color: var(--meta-text); }
.meta--wide{ letter-spacing: .12em; text-transform: uppercase; }
.rule{ border: 0; border-top: 1px solid var(--concrete); }
.rule--dashed{ border: 0; border-top: 1px dashed var(--concrete); }
.centered{ text-align: center; }

/* ── buttons ────────────────────────────────────────────────────────
   AppButton: ink fill with a page-coloured uppercase label, raised
   bevel, and on press the bevel inverts while the label travels a pixel
   down-right, the way a physical key does. */

.actions{ display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

.btn{
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 13px; font-weight: 400;
  text-transform: uppercase; letter-spacing: .1em;
  padding: 11px 18px; min-height: 48px; cursor: pointer;
  /* Flat, not the app's 3px raised bevel. The bevel belongs to the nav keys,
     which are chrome; a button sitting flush against a 1px field needs the
     same weight of edge as the field, or the seam between them reads as a
     step. */
  border: 1px solid var(--ink);
}
.btn--primary{ background: var(--ink); color: var(--page); }
.btn--primary:visited, .btn--primary:hover{ color: var(--page); }
.btn--secondary{ background: var(--page); color: var(--ink); }
.btn--secondary:visited, .btn--secondary:hover{ color: var(--ink); }
/* No bevel to invert, so the press is carried by the fill and the 1px
   legend nudge below. */
.btn--primary:active{ background: var(--link); }
.btn--secondary:active{ background: var(--bevel-face-pressed); }
.btn:active > span{ transform: translate(1px, 1px); }

/* ── countdown ──────────────────────────────────────────────────────
   One palette colour per unit, exactly as components/countdown.tsx.
   That file notes the two pale units are a deliberate call rather than
   an oversight; the site repeats it, and prints the target date in plain
   text underneath so nothing is carried by colour alone. */

.countdown{ display: flex; align-items: flex-start; justify-content: center; }
.countdown__sep{ align-self: flex-start; }
.countdown__cell{ text-align: center; }
.countdown__num{
  font-family: var(--font-mono); font-weight: 700;
  font-size: clamp(30px, 6.6vw, 62px); line-height: 1;
  font-variant-numeric: tabular-nums;
}
.countdown__label{
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase; margin-top: 8px;
}
.countdown__sep{
  font-family: var(--font-mono); font-weight: 400;
  font-size: clamp(20px, 4.2vw, 40px); line-height: 1;
  color: var(--meta-text); padding: 0 clamp(2px, 1vw, 10px);
}
.countdown [data-unit="days"] .countdown__num,
.countdown [data-unit="days"] .countdown__label{ color: var(--crimson); }
.countdown [data-unit="hrs"] .countdown__num,
.countdown [data-unit="hrs"] .countdown__label{ color: var(--velour-lilac); }
.countdown [data-unit="min"] .countdown__num,
.countdown [data-unit="min"] .countdown__label{ color: var(--link); }
.countdown [data-unit="sec"] .countdown__num,
.countdown [data-unit="sec"] .countdown__label{ color: var(--marigold); }

/* ── palette progress bar ───────────────────────────────────────────
   AppProgressBar's segmented mode: each block takes the next colour off
   the masthead band, so a filled bar rebuilds the header's stripe. */

/* ── badges ─────────────────────────────────────────────────────── */

.badge{
  display: inline-block; font-size: 9px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 2px 6px; border: 1px solid var(--concrete); vertical-align: middle;
}
.badge--new{ background: var(--cobalt); color: var(--studio); border-color: var(--cobalt); }
.badge--pinned{ background: var(--marigold); color: var(--ink); }
.badge--locked{ background: var(--crimson); color: var(--studio); border-color: var(--crimson); }

/* ── tables ─────────────────────────────────────────────────────── */

.board{ width: 100%; border-collapse: collapse; font-size: 12.5px; }
.board caption{ text-align: left; font-size: 11px; color: var(--meta-text); padding: 0 0 8px; }
.board th{
  background: var(--periwinkle); color: var(--ink);
  text-align: left; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; padding: 7px 10px; border: 1px solid var(--concrete);
}
.board td{ padding: 8px 10px; border: 1px solid var(--concrete); vertical-align: top; }
.board tbody tr:nth-child(even) td{ background: var(--row-alt); }
.board tbody tr:hover td{ background: var(--periwinkle); }
.board .num, .board .phase{ white-space: nowrap; font-size: 12px; }
.board .title{ font-weight: 700; }
.board .desc{ display: block; font-size: 11px; color: var(--meta-text); font-weight: 400; margin-top: 3px; }
.board .stripe-marigold{ border-left: 4px solid var(--marigold); }

/* ── member squares, option markers ─────────────────────────────── */

/* ── quote, code ─────────────────────────────────────────────────── */

.quote{
  background: var(--page); border: 1px solid var(--concrete);
  border-left: 3px solid var(--wig-pink); padding: 10px 12px;
}
.quote cite{ display: block; font-size: 11px; color: var(--meta-text); font-style: normal; margin-top: 6px; }

.codeblock{
  background: var(--cream-curl); border: 1px solid var(--concrete);
  font-size: 12px; padding: 10px 12px; overflow-x: auto; white-space: pre;
}

/* ── art ────────────────────────────────────────────────────────── */

/* Face and tracking only — the size lives with the lamb further up, so the
   two cannot drift apart. A font-size here would win by source order and
   silently break the ratio. */
.wordmark{
  font-family: var(--font-display); font-weight: 700;
  line-height: .95; letter-spacing: -0.02em;
  text-align: center;
}

/* Two of the corner glyphs are real controls, so they are buttons: reachable
   by keyboard, with a visible focus ring. The other two stay ornament. */
.letter__btn{
  background: none; border: 0; padding: 0; margin: 0;
  display: inline-flex; align-items: center; cursor: pointer; color: inherit;
}
.letter__btn:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }
/* Starred: the glyph fills with whichever palette colour it was given. */
.letter__btn[aria-pressed="true"] svg path{ fill: var(--star-fill); stroke: var(--star-fill); }

/* ── the goat, in a dialog ───────────────────────────────────────────
   <dialog> rather than a div: it traps focus, closes on Escape and
   restores focus to the button that opened it, none of which is worth
   re-implementing. */
.modal{
  border: 1px solid var(--ink); background: var(--page); color: var(--ink);
  padding: 12px; width: min(400px, 88vw); max-width: none;
  /* Anchored to the icon that opens it rather than centred, so position is
     set from script; margin:0 defeats the centring a <dialog> does by
     default via auto margins. */
  position: fixed; margin: 0; inset: auto;
}
/* The page behind stays exactly as it was — no dim. The dialog is still
   modal, so Escape and the focus trap still work; only the tint is gone. */
.modal::backdrop{ background: transparent; }
/* The one shadow on the site. Everything else is flat by DESIGN.md §3, but
   with no backdrop tint a popup needs some way to sit above the page rather
   than look pasted into it. Deliberate exception, and it has to be
   !important to beat the blanket `* { box-shadow: none !important }`. */
.modal{ box-shadow: 0 2px 8px rgba(27, 34, 48, .14) !important; }
.modal img{ width: 100%; height: auto; display: block; }
.modal__caption{
  margin-top: 10px; text-align: center;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
}
.modal__caption span{ color: var(--meta-text); line-height: 1.7; }
.modal--note{ width: min(360px, 88vw); }
.modal__title{
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  margin-bottom: 10px; padding-right: 28px;
}
.modal--note form{
  display: grid; grid-template-columns: auto 1fr;
  gap: 8px 10px; align-items: center;
}
.modal--note form label{
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--meta-text);
}
/* The note label sits against the top of its box rather than the middle. */
.modal--note form label[for="note-body"]{ align-self: start; padding-top: 10px; }
.modal--note .hp{ grid-column: 1 / -1; }
.modal--note input[type="text"],
.modal--note textarea{
  width: 100%; font-family: var(--font-mono); font-size: 13px;
  padding: 10px; background: var(--page); color: var(--ink);
  border: 1px solid var(--ink);
  -webkit-appearance: none; appearance: none;
}
.modal--note textarea{ resize: vertical; min-height: 92px; line-height: 1.5; }
.modal--note input:focus, .modal--note textarea:focus{
  background: var(--velour-lilac); outline: none;
}
.modal--note .is-sent, .modal--note .is-sent:focus{ background: var(--hood-green); }
.modal--note .btn{ grid-column: 2; justify-self: end; }
.modal--note #note-status{ margin-top: 8px; }

.modal__close{
  position: absolute; top: 6px; right: 6px;
  width: 30px; height: 30px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--page); border: 1px solid var(--ink); cursor: pointer;
}
.modal__close svg{
  width: 14px; height: 14px;
  fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round;
}
.modal__close:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── the home box as a letter ────────────────────────────────────────
   Addressing lines, a dashed rule, the body, a sign-off — the shape the app
   uses for the letter a match arrives in. The head is left-aligned against
   the same measure as the form beneath it; everything between stays centred. */

/* The routing sits in the corners of the sheet rather than on the body's
   measure — it is the envelope, not the letter. */
.letter__meta{
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  align-items: flex-start; justify-content: space-between;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--meta-text);
}
.letter__head{ text-align: left; }
.letter__head > div{ display: flex; gap: 10px; padding: 1px 0; align-items: baseline; }
.letter__head dt{ flex: 0 0 46px; }
.letter__head dd{ margin: 0; color: var(--ink); }

/* Three right-aligned rows, as a mail client stacks them: message position,
   then print/open, then the date with its actions. */
.letter__aside{
  margin-left: auto; text-align: right;
  display: flex; flex-direction: column; align-items: flex-end; gap: 7px;
  white-space: nowrap; color: var(--ink);
}
.letter__toolbar{ display: flex; align-items: center; gap: 11px; }
.letter__icons{ display: flex; align-items: center; gap: 11px; }

.letter__aside svg{
  width: 15px; height: 15px; flex: 0 0 auto;
  fill: none; stroke: var(--meta-text); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Glyphs that are a shape rather than a line: the keyboard, the caret, and
   every dot. */
.letter__aside svg.solid > *{ fill: var(--meta-text); stroke: none; }
.letter__aside svg .punch > *{ fill: var(--page); stroke: none; }
.letter__aside svg .dot{ fill: var(--meta-text); stroke: none; }
/* Its viewBox is cropped to the artwork, so these are the drawn size rather
   than a box the drawing sits inside — sized so the two heads stand as tall
   as the star and the reply arrow beside them. */
.letter__aside svg.twoface{ width: 18.15px; height: 11.97px; }

/* Set as the addressing lines are, and parked in the opposite corner — the
   sign-off is part of the envelope, not part of the body copy. */
.letter__sign{
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  line-height: 1.9; color: var(--ink); text-align: right;
}

/* ── form ───────────────────────────────────────────────────────── */

/* The field and its button are one control: no gap, stretched to a common
   height, and the button pulled back a pixel so the two 1px edges collapse
   into a single shared seam rather than stacking into a 2px rule. */
.form{ display: flex; gap: 0; align-items: stretch; }
.form .btn{ margin-left: -1px; flex: 0 0 auto; }
/* In the hero the form *is* the call to action, so it sits centred on the
   measure rather than running the full column width. */
.hero .form{ max-width: 470px; margin-inline: auto; }
/* .lede is capped at 62ch, so it needs centring as a block as well as
   having its text centred. */
.hero .lede{ margin-inline: auto; }
.form label{
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--meta-text); display: block; margin-bottom: 6px;
}
.form__field{ flex: 1 1 auto; min-width: 0; display: flex; }
/* A flat white field rather than DESIGN.md §2's inset bevel, which put a
   dark --heather edge along the top and read as a grey bar even though the
   fill was already white. 1px --ink instead, to pair with the solid button
   beside it.
   appearance:none is load-bearing: WebKit draws its own inset chrome on a
   text field whatever the border says, so without it the bevel comes back
   in Safari even though nothing in this file asks for one. */
input[type="email"]{
  width: 100%; font-family: var(--font-mono); font-size: 13px;
  padding: 12px; min-height: 48px; background: var(--page); color: var(--ink);
  border: 1px solid var(--ink);
  -webkit-appearance: none; appearance: none;
}
/* Two states, both palette fills, both carrying --ink text:
     focused  -> --velour-lilac, the field you are filling in
     sent     -> --hood-green, the field you have finished with
   The global focus-visible outline is suppressed here by request: it drew a
   second black rule outside the field's own. The lilac fill is the focus
   indicator on its own as a result — see web/README.md, which records what
   that costs. */
input[type="email"]:focus{ background: var(--velour-lilac); }
input[type="email"]:focus, input[type="email"]:focus-visible{ outline: none; }
input[type="email"].is-sent,
input[type="email"].is-sent:focus{ background: var(--hood-green); }

/* Chrome paints a recognised field with its own pale blue and ignores
   `background`, which is where the light blue was coming from. The only
   thing that overrides it is an inset shadow the width of the field — hence
   the exception to the no-shadows rule above, which this has to outrank on
   specificity since both are !important. */
input[type="email"]:-webkit-autofill{
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: inset 0 0 0 100px var(--page) !important;
  box-shadow: inset 0 0 0 100px var(--page) !important;
}
input[type="email"]:-webkit-autofill:focus{
  -webkit-box-shadow: inset 0 0 0 100px var(--velour-lilac) !important;
  box-shadow: inset 0 0 0 100px var(--velour-lilac) !important;
}
input[type="email"].is-sent:-webkit-autofill,
input[type="email"].is-sent:-webkit-autofill:focus{
  -webkit-box-shadow: inset 0 0 0 100px var(--hood-green) !important;
  box-shadow: inset 0 0 0 100px var(--hood-green) !important;
}
input[type="email"]:focus::placeholder{ color: var(--ink); opacity: .55; }
input::placeholder{ color: var(--meta-text); opacity: 1; }
.hp{ position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ── pips + footer ──────────────────────────────────────────────── */

.pips{ font-size: 12px; color: var(--meta-text); padding: 4px 0; }
.pips b{ color: var(--ink); }

.footer{
  max-width: 960px; margin: 0 auto 28px; padding: 0 12px;
}
.footer__inner{
  padding-top: 12px;
  display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: baseline;
}
/* Name left, notice right; the first line takes the slack between them. */
.footer .meta:first-child{ margin-right: auto; }

/* ── responsive: stack rows, never scroll a table ───────────────── */

@media (max-width: 720px){
  .display{ font-size: 26px; }
  /* The lamb shares the line, so its width is what caps the type. Trimming
     --lamb-scale from 2.15 to 1.8 on a phone buys the wordmark about 2px:
     the ceiling moves from 38.8px to 40.6px at 375px, and from 32.7px to
     34.3px at 320px. 10.6vw lands just under both. */
  .wordmark{ --wordmark: clamp(32px, 10.6vw, 80px); --lamb-scale: 1.8; }
  /* Wrapped onto two rows the links were spaced like paragraphs. The row gap
     goes and the padding comes down, while the type goes up — a 33px target
     rather than 44px. Still well over the 24px WCAG 2.2 floor. */
  /* The letterhead was six rows on a phone, three of them ornament stacked
     down the right. The two purely decorative toolbars go — they are already
     aria-hidden, so nothing is lost to anyone — leaving the date beside the
     buttons that actually do something. The addressing rows tighten up too. */
  .letter__toolbar[aria-hidden="true"]{ display: none; }
  .letter__meta{ gap: 2px 12px; }
  .letter__head > div{ padding: 0; }
  /* The date is a value, not a label, so it lines up with the values above
     it — 56px in, which is the 46px label column plus its 10px gap. The
     icons take the far edge, so the row spans the block rather than
     trailing off mid-way. */
  .letter__aside{
    gap: 0;
    width: 100%;
    margin-left: 0;
    align-items: stretch;
    text-align: left;
  }
  .letter__aside .letter__toolbar{
    padding-left: 56px;
    justify-content: space-between;
  }

  .toplinks{ gap: 0 13px; }
  .toplinks a{ padding: 8px 2px; font-size: 13px; }
  /* The clock had been pinned at its 30px floor on a phone, with room to
     spare: 375px fits 51px before the row reaches the column edge. */
  .countdown__num{ font-size: clamp(34px, 11.5vw, 56px); }
  .countdown__sep{ font-size: clamp(22px, 7vw, 36px); }
  .countdown__label{ font-size: 10px; }
  .tabs a{ min-width: 33.33%; font-size: 10px; letter-spacing: .08em; }
  .masthead{ height: 42px; }
  .masthead svg{ height: 24px; }
  .lamb{ width: 150px; }

  .board, .board tbody, .board tr, .board td{ display: block; width: 100%; }
  /* A table-caption inside a block-level table collapses to its shrink-to-fit
     width, which sets the line one word at a time. */
  .board caption{ display: block; width: 100%; }
  .board thead{ position: absolute; left: -9999px; }
  .board tr{ border: 1px solid var(--concrete); margin-bottom: 10px; }
  .board td{ border: 0; border-bottom: 1px dashed var(--concrete); }
  .board tr td:last-child{ border-bottom: 0; }
  .board tbody tr:nth-child(even) td{ background: transparent; }
  .board tbody tr:nth-child(even){ background: var(--row-alt); }
  .board td[data-th]::before{
    content: attr(data-th) ": ";
    font-size: 11px; letter-spacing: .06em; color: var(--meta-text);
  }
  .hero{ padding: 0; }
}

@media (prefers-reduced-motion: reduce){
  *{ animation: none !important; }
}
/* --- dither bands: Bayer 4x4, generated from brand-header.tsx --- */
