/* ──────────────────────────────────────────────────────────────────
   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;
}
/* The page you are on: --ink and bold, against --link blue for the rest.
   Colour alone was not enough — #2F5B92 and #1B2230 are both dark and read
   as near enough the same at 12px — and DESIGN.md §5 says state is never to
   be signalled by colour alone anyway, so the weight does the work and the
   colour reinforces it. */
.toplinks a[aria-current="page"]{ color: var(--ink); font-weight: 700; }
.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;
}
/* On a prose page the sign-off sits on the same measure as the body copy and
   aligns with the start of it, not the end — it reads as the last thing the
   writer said rather than as a stamp in the corner. The extra top margin is
   the blank line between it and the final paragraph. */
.sheet .letter__sign{
  max-width: var(--measure); margin-inline: auto;
  text-align: left;
  margin-top: 2.2em;
}
.sheet .letter__sign time{ color: var(--meta-text); }
/* Not in the letter, though: there it has to line up with the routing in the
   opposite corner, which spans the full width of the box rather than sitting
   on the body's measure — and stays right-aligned, against the prose rule
   above which turns the sign-off left for narrative pages. */
.hero .letter__sign{
  max-width: none; margin-inline: 0;
  text-align: right;
  margin-top: 14px;
}

/* ── 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 ───────────────── */

/* ── letterhead, narrow screens only ─────────────────────────────────
   The wrapping arrangement is for widths where the glyphs genuinely
   have to break. Given a tablet's room they all fit on a single line,
   which reads as a dense strip rather than a letterhead — so above
   520px the three-row corner stack takes over again. */
@media (max-width: 520px){
  /* The count goes on a phone — it is the widest piece of ornament and the
     least informative, and dropping it keeps the glyph rows from pushing the
     addressing block narrower. */
  .letter__count{ display: none; }

  /* The adornment stays on a phone, but the three toolbars stop being three
     stacked rows: the aside becomes one wrapping row, so the glyphs flow and
     break where they run out of width instead of each group claiming a line
     of its own. */
  .letter__meta{ gap: 2px 12px; }
  .letter__head > div{ padding: 0; }
  /* Beside the addressing rows, not beneath them: no width:100%, so it stays
     a flex sibling of the dl and shares those lines, pushed to the right by
     the auto margin it inherits. It wraps within whatever width is left. */
  .letter__aside{
    /* flex:1 with min-width:0 is what keeps it on the same line as the
       addressing rows. Left at its natural width it is wider than the space
       the dl leaves, so the wrap on .letter__meta pushes the whole block to
       its own line — shrinking it instead makes the glyphs wrap inside it. */
    flex: 1 1 0;
    min-width: 0;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    align-content: flex-start;
    gap: 2px 10px;
    text-align: right;
  }
  .letter__head{ flex: 0 0 auto; }
  /* The rows wrap inside themselves as well. Without this the date-and-icons
     row is wider than the space left beside the addressing block, and
     justify-content:flex-end makes an over-wide flex row spill past its LEFT
     edge — which is how the date ended up printed over "THE ALGORITHM". */
  .letter__aside .letter__toolbar{
    justify-content: flex-end;
    flex-wrap: wrap;
    white-space: normal;
    /* Column gap only. The toolbar's 11px gap was set to space glyphs along
       a row; once the row wraps it spaces the lines too, so the date sat
       28px from its icons while every other line was 17px apart. Row gap
       matched to the aside's. */
    column-gap: 11px;
    row-gap: 2px;
  }
}

@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. */
  .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 --- */
