/* =====================================================================
   SOMEWHERE
   Built from reference/approved-desktop-mockup.png in the design kit.
   Warm, intimate, urban, editorial: the typography and the photography
   carry the brand. Square corners, fine rules, deliberate asymmetry.
   ===================================================================== */

:root{
  --paper:#EFEBDD;
  --oxblood:#34121F;
  --tomato:#D94329;
  --rule:#918078;
  --rule-faint:rgba(145,128,120,.32);
  --ink-soft:rgba(52,18,31,.72);

  --display:'Anton','Haettenschweiler','Arial Narrow',sans-serif;
  --body:'Inter',-apple-system,'Helvetica Neue',Arial,sans-serif;

  --gutter:clamp(18px,2.9vw,34px);
  --t-control:220ms;
  --t-reveal:520ms;
  --ease:cubic-bezier(.16,.68,.28,1);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;overflow-x:clip}
body{
  margin:0;background:var(--paper);color:var(--oxblood);
  font-family:var(--body);font-size:15px;line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
img{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit}

::selection{background:var(--tomato);color:var(--paper)}

:where(a,button,input,textarea,select,[tabindex]):focus-visible{
  outline:2px solid var(--tomato);outline-offset:3px;
}

/* Small uppercase labels: generous tracking, per the brief. */
.eyebrow,.label,.caption-tr,.caption-br,.caption-under,.line-meta,.index,.fineprint{
  font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.17em;
}

.display{
  font-family:var(--display);font-weight:400;
  letter-spacing:-.004em;line-height:.86;margin:0;
  /* Anton sits high in its em box; this pulls the optical top to the grid. */
  text-transform:none;
}
.display em{font-style:normal;color:var(--tomato)}


/* ── Masthead ─────────────────────────────────────────────── */

.masthead{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:26px;padding:0 var(--gutter);min-height:59px;
  border-bottom:1px solid var(--rule-faint);
}
.wordmark img{height:19px;width:auto}
.masthead-nav{display:flex;gap:30px;justify-content:flex-end;font-size:13px;font-weight:500}
.masthead-nav a{position:relative;padding-bottom:2px}
.masthead-nav a::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform var(--t-control) var(--ease);
}
.masthead-nav a:hover::after{transform:scaleX(1)}
.masthead-right{display:flex;align-items:center;gap:20px}

.btn{
  display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;
  font-size:13px;font-weight:600;padding:11px 18px;
  transition:background-color var(--t-control) var(--ease),
             color var(--t-control) var(--ease);
}
.btn-accent{background:var(--tomato);color:#fff}
.btn-accent:hover{background:#c23a22}
.btn-dark{background:var(--oxblood);color:var(--paper);padding:14px 22px;font-size:14px}
.btn-dark:hover{background:#4a1d2c}
.btn-wide{width:100%;justify-content:center;padding:15px}

.underlined{border-bottom:1px solid currentColor;padding-bottom:2px;font-size:14px;font-weight:500}
.quiet-link{
  background:none;border:0;border-bottom:1px solid currentColor;padding:1px 0;
  cursor:pointer;font-size:11px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft);
  transition:color var(--t-control) var(--ease);
}
.quiet-link:hover{color:var(--tomato)}


/* ── Hero ─────────────────────────────────────────────────── */

.hero{
  display:grid;grid-template-columns:39fr 61fr;align-items:stretch;
  border-bottom:1px solid var(--rule-faint);
}
.hero-copy{padding:38px var(--gutter) 40px;display:flex;flex-direction:column;justify-content:center}
.eyebrow{color:var(--oxblood);margin:0 0 20px}

.hero-copy .display{
  /* The heading fills almost the full column in the reference. */
  font-size:clamp(58px,11.3vw,178px);
  margin-bottom:26px;
}
.hero-body{margin:0 0 26px;font-size:15.5px;line-height:1.52;max-width:34ch}
.hero-actions{display:flex;align-items:center;gap:22px;flex-wrap:wrap;margin-bottom:22px}
.fineprint{margin:0;color:var(--ink-soft);letter-spacing:.13em}

.hero-art{position:relative;min-height:420px;isolation:isolate}
.hero-photo{margin:0;height:100%}
.hero-photo img{width:100%;height:100%;object-fit:cover;object-position:52% 42%}
/* Overlaid on the photograph, so light — the reference sets both of these
   over dark areas of the image, not on paper. */
.caption-under,.caption-tr{
  position:absolute;margin:0;color:rgba(255,255,255,.82);
  text-shadow:0 1px 3px rgba(0,0,0,.45);line-height:1.7;
}
.caption-under{left:14px;bottom:14px}
.caption-tr{top:26px;right:18px;text-align:left;max-width:74px}
.caption-tr .rule-sm{background:rgba(255,255,255,.6)}

/* The paper block that interrupts the photo's lower-right corner. It holds
   the street inset and its caption side by side, which is why the caption
   reads as dark-on-paper while the two above are light-on-photo. */
.hero-corner{
  z-index:2;position:absolute;right:0;bottom:0;
  width:clamp(240px,48%,366px);
  background:var(--paper);
  padding:10px 0 10px 10px;
  display:grid;grid-template-columns:1fr 84px;align-items:end;gap:12px;
}
.hero-inset{margin:0}
.hero-inset img{width:100%;aspect-ratio:240/260;object-fit:cover;object-position:50% 32%}
.caption-br{
  margin:0 var(--gutter) 6px 0;color:var(--ink-soft);
  line-height:1.7;white-space:nowrap;
}
.rule-sm{display:block;width:22px;height:1px;background:var(--rule);margin-top:9px}

/* ── The three-part strip ─────────────────────────────────── */

.strip{
  display:grid;grid-template-columns:repeat(3,1fr);
  border-bottom:1px solid var(--rule-faint);
}
.strip-item{
  display:flex;align-items:center;gap:16px;
  padding:22px var(--gutter);min-height:95px;
}
.strip-item + .strip-item{border-left:1px solid var(--rule-faint)}
.index{color:var(--tomato);align-self:flex-start;margin-top:6px}
.strip-item h2{
  font-family:var(--display);font-weight:400;margin:0;
  font-size:clamp(26px,3.4vw,44px);line-height:1;letter-spacing:.004em;
  text-transform:uppercase;
}


/* ── The board ────────────────────────────────────────────── */

.board{
  display:grid;grid-template-columns:1fr 1fr 1fr;
  padding:34px var(--gutter) 60px;gap:0 34px;
}
.board-intro{padding-right:30px;border-right:1px solid var(--rule-faint)}
.board-intro .display{font-size:clamp(30px,3.5vw,45px);margin-bottom:18px}
.board-body{margin:0 0 22px;max-width:31ch;line-height:1.55}

.city-control{border-top:1px solid var(--rule-faint);padding-top:16px}
.city-control .label{margin:0 0 10px;color:var(--ink-soft)}

.board-lines{display:contents}
.line{padding-left:0}
.board-lines .line + .line{padding-left:34px;border-left:1px solid var(--rule-faint)}

.line-photo{margin:0 0 14px;position:relative;overflow:hidden}
.line-photo img{width:100%;aspect-ratio:2.35/1;object-fit:cover;
  transition:transform var(--t-reveal) var(--ease)}
.line-photo:hover img{transform:scale(1.015)}
.scrawl{
  position:absolute;top:11%;right:5%;margin:0;max-width:40%;
  font-family:'Georgia',serif;font-style:italic;
  font-size:clamp(12px,1.2vw,16px);line-height:1.3;
  color:#4a3f38;text-align:left;
}

.line-meta{display:flex;justify-content:space-between;gap:12px;margin:0 0 10px;color:var(--ink-soft)}
.line-left{letter-spacing:.09em;text-transform:none;font-weight:500}
.line-body{margin:0 0 18px;font-size:clamp(18px,1.75vw,23px);line-height:1.32}
.answer{
  color:var(--tomato);font-size:13px;font-weight:600;
  border-bottom:1px solid currentColor;padding-bottom:2px;
  display:inline-flex;gap:6px;align-items:center;
}
/* Labelled, unmissably, because these two are illustrative and the board is
   otherwise real. A fabricated line presented as genuine is the one thing
   this product cannot do. */
.is-example .line-body::after{
  content:'Example';display:inline-block;vertical-align:middle;
  margin-left:9px;font-family:var(--body);font-size:9px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;
  border:1px solid var(--rule-faint);padding:3px 6px;color:var(--ink-soft);
}


/* ── Colophon ─────────────────────────────────────────────── */

.colophon{
  border-top:1px solid var(--rule-faint);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px;
  padding:26px var(--gutter);font-size:12px;
}
.colophon-tag{margin:0;font-weight:600}
.colophon nav{display:flex;gap:20px;justify-content:center}
.colophon nav a{color:var(--ink-soft);transition:color var(--t-control) var(--ease)}
.colophon nav a:hover{color:var(--tomato)}
.colophon-meta{margin:0;text-align:right;color:var(--ink-soft)}


/* ── Composer ─────────────────────────────────────────────── */

.composer{
  border:0;padding:0;max-width:520px;width:calc(100% - 32px);
  background:var(--paper);color:var(--oxblood);
}
.composer::backdrop{background:rgba(52,18,31,.42)}
.composer-inner{padding:30px}
.composer-dismiss{position:absolute;top:10px;right:12px}
.composer-dismiss button{background:none;border:0;font-size:22px;line-height:1;cursor:pointer;color:var(--ink-soft)}
.composer .display{margin-bottom:22px}

.composer-form label{display:block;font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:.15em;margin:18px 0 7px}
.composer-form label:first-of-type{margin-top:0}
.opt{text-transform:none;letter-spacing:0;font-weight:400;color:var(--ink-soft)}

.composer-form textarea,.composer-form input[type=text],.composer-form input[type=email]{
  width:100%;border:1px solid var(--rule);background:#F7F4EA;color:var(--oxblood);
  padding:13px 14px;font:inherit;outline:none;
  transition:border-color var(--t-control) var(--ease);
}
.composer-form textarea{height:110px;resize:none;font-size:17px;line-height:1.35}
.composer-form textarea:focus,.composer-form input:focus{border-color:var(--tomato)}
.composer-form ::placeholder{color:rgba(52,18,31,.4)}

.count{display:flex;justify-content:space-between;margin:7px 0 0;
  font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-soft)}
.note{font-size:12px;line-height:1.45;margin:9px 0 0;color:var(--ink-soft)}
.note-quiet{font-size:11px}
#audience-note{border-left:2px solid var(--tomato);padding-left:10px}

.consent{display:flex;gap:9px;align-items:flex-start;margin:20px 0 0;
  font-size:11px!important;text-transform:none!important;letter-spacing:0!important;
  font-weight:400!important;line-height:1.45}
.consent input{margin-top:2px;flex:none}
.consent a{border-bottom:1px solid var(--tomato)}
.composer-form .btn{margin-top:20px}
.form-message{font-size:12px;margin:12px 0 0;font-weight:500}
.form-message.error{color:#A32918}
.composer-done{text-align:center;padding:20px 0}
.composer-done h3{font-family:var(--display);font-weight:400;font-size:34px;margin:0 0 10px}


/* ── Reveal ───────────────────────────────────────────────── */

@media(prefers-reduced-motion:no-preference){
  .hero-copy > *,.hero-art,.strip-item,.board-intro,.board-lines .line{
    animation:rise var(--t-reveal) var(--ease) both;
  }
  .hero-art{animation-delay:60ms}
  .strip-item:nth-child(2){animation-delay:40ms}
  .strip-item:nth-child(3){animation-delay:80ms}
  .board-lines .line:nth-child(2){animation-delay:60ms}
}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}


/* ── Responsive ───────────────────────────────────────────── */

@media(max-width:900px){
  .hero{grid-template-columns:1fr}
  .hero-copy{padding-bottom:30px}
  .hero-art{min-height:0;aspect-ratio:1/1}
  .caption-tr{display:none}
  .hero-inset{right:6%;bottom:-28px;width:36%;max-width:190px}
  .caption-br{bottom:-18px;right:auto;left:var(--gutter)}
  .board{grid-template-columns:1fr;gap:34px}
  .board-intro{border-right:0;padding-right:0;border-bottom:1px solid var(--rule-faint);padding-bottom:26px}
  .board-lines .line + .line{padding-left:0;border-left:0;border-top:1px solid var(--rule-faint);padding-top:26px}
  .board-lines{display:flex;flex-direction:column;gap:26px}
  .colophon{grid-template-columns:1fr;text-align:center;gap:14px}
  .colophon nav{flex-wrap:wrap}
  .colophon-meta{text-align:center}
}

@media(max-width:620px){
  .masthead{grid-template-columns:auto auto;gap:12px}
  .masthead-nav{display:none}
  .masthead-right{gap:10px}
  .hero-actions{gap:16px}
  .strip{grid-template-columns:1fr}
  .strip-item{min-height:0;padding:15px var(--gutter)}
  .strip-item + .strip-item{border-left:0;border-top:1px solid var(--rule-faint)}
  .composer-inner{padding:22px}
}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
}


/* ── City picker ──────────────────────────────────────────── */
/* A native <select> of 52 cities opens an unstyleable OS list that fills the
   screen. This is the replacement: capped height, filters as you type. */

.cp{position:relative;display:inline-block;width:100%}
.cp-trigger{
  display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;
  border:1px solid var(--rule);background:#F7F4EA;color:var(--oxblood);
  padding:13px 14px;font:inherit;font-size:15px;cursor:pointer;text-align:left;
  transition:border-color var(--t-control) var(--ease);
}
.cp-trigger:hover,.cp-trigger[aria-expanded="true"]{border-color:var(--oxblood)}
.cp-caret{width:10px;height:6px;flex:none;background:currentColor;
  clip-path:polygon(0 0,100% 0,50% 100%);
  transition:transform var(--t-control) var(--ease)}
.cp-trigger[aria-expanded="true"] .cp-caret{transform:rotate(180deg)}

.cp-panel{
  position:absolute;z-index:80;top:calc(100% - 1px);left:0;right:0;
  max-width:min(340px,calc(100vw - 32px));
  background:var(--paper);border:1px solid var(--oxblood);padding:6px;
}
.cp-search{width:100%;border:1px solid var(--rule);background:#F7F4EA;
  padding:9px 11px;font:inherit;font-size:13px;color:var(--oxblood);outline:none;margin-bottom:5px}
.cp-list{list-style:none;margin:0;padding:0;max-height:232px;overflow-y:auto;overscroll-behavior:contain}
.cp-list li{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 11px;font-size:14px;cursor:pointer}
.cp-list li.cp-active{background:var(--oxblood);color:var(--paper)}
.cp-list li[aria-selected="true"]{box-shadow:inset 2px 0 0 var(--tomato)}
.cp-live{color:var(--tomato);font-weight:700}
.cp-list li.cp-active .cp-live{color:var(--paper)}
.cp-none{margin:0;padding:11px;font-size:13px;color:var(--ink-soft)}

.city-control .cp{max-width:330px}

/* The composer's two pickers sit in a narrower column. */
.composer .cp-trigger{font-size:15px}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Language switcher, in the masthead. */
.lang-switch{display:flex;gap:9px;font-size:11px;font-weight:500;color:var(--ink-soft)}
.lang-switch a{border-bottom:1px solid transparent;transition:color var(--t-control) var(--ease),
  border-color var(--t-control) var(--ease)}
.lang-switch a:hover{color:var(--tomato);border-bottom-color:currentColor}
.lang-switch [aria-current]{color:var(--oxblood);font-weight:600}
@media(max-width:620px){.lang-switch{display:none}}
/* =====================================================================
   SOMEWHERE — fidelity corrections against reference/approved-desktop-mockup.png
   Append to the END of style.css. Every rule here relies on source order
   to win (media queries add no specificity), so the @media block near the
   bottom MUST stay after the desktop rules it re-states.
   All figures below are pixel measurements taken off /tmp/reference.png
   and /tmp/build-desktop.png at 1190x1322.
   ===================================================================== */


/* ── 1. Tokens ─────────────────────────────────────────────────────────
   THE RULES. Sampled at every divider, the reference's rule core is
   rgb(144,131,120); --rule (#918078) is rgb(145,128,120) — an exact
   match. The build composites rgba(...,.32) to rgb(209,200,189), a
   quarter of the ink (dE76 25.5). The reference's rule also straddles a
   fractional device offset and carries ~1.7px-equivalents of ink, so
   full strength is if anything still conservative. This is what makes
   the strip's vertical separators and the board's column rules read as
   structure rather than as ghosts — the brief names them ("fine divider
   rules", "slim vertical separators", "open columns... not elevated
   cards"), and they are the only thing establishing the board's columns.
   Touches all 12 uses plus the EXAMPLE chip border.

   THE TOMATO. Median over 26,647 red pixels inside 'coffee.': reference
   rgb(206,71,48), build rgb(217,67,41). Same hue angle (39.0 vs 39.8),
   ~10% more chroma in the build. Not an artifact of the mockup's colour
   cast — paper and oxblood both measure within 2 units on the same
   image, and the build's red is HIGHER, not lower. Side benefit: the
   white-on-tomato masthead CTA is 13px/600, which WCAG AA scores as
   normal text needing 4.5:1. #D94329 gives 4.39:1 and fails; #CE4730
   gives 4.60:1 and passes. */
:root{
  --rule-faint:#918078;
  --tomato:#CE4730;
}
.btn-accent:hover{background:#B93B26}   /* rebalanced to the new base: dL* 5.7, matching the old 5.5 step */


/* ── 2. The display face ───────────────────────────────────────────────
   I measured 'another' glyph-by-glyph in both images at four ink
   thresholds. The letterform WIDTHS are the same:
       ref   a59 n59 o59 t38 h60 e59 r45   gaps 3,3,2,3,3,3   span 395
       build a58 n58 o59 t37 h59 e58 r41   gaps 8,8,5,6,8,8   span 413
   The reference's face is narrower per unit of HEIGHT (x-height 110 vs
   Anton's 98.5 at the same glyph widths) and set with 2.8px gaps where
   the build has 7.2px. So the 18px overrun is entirely tracking, not
   size — and -.035em removes 4.2px per gap, landing on 3.0px.

   That matters structurally: a grid track's automatic minimum is
   min-content, and "another" is one unbreakable word whose advance box
   was 416px against a 396px measure, which is why the photograph's edge
   measures x=484 instead of the reference's x=464 — the hero has been
   rendering 40.7/59.3, not the specified 39/61, at every width below
   1693px. At -.035em the advance box is 387px (+68px padding = 455px
   inside the 464px track) and the split comes back. Ink lands at 388px
   against the reference's 395px; the 7px is Anton's narrower 'r' and is
   not recoverable without changing the face. */
.display{letter-spacing:-.035em}

/* Leading, hero only. The reference's baseline-to-baseline is 140px on a
   110px x-height = 1.2727. Anton's x-height is 1500/2048 = .7324em, so
   the matching line-height is 1.2727 x .7324 = .932. At .86 the gap band
   between line 1's baseline and line 2's x-height top is 14 rows
   carrying 85px of ink per row; the reference's is 30 rows carrying 36 —
   the descender of "Stay" and the ascenders of "another" are packed into
   half the air they should have. This also adds 28.3px to the h1 box,
   which is most of the reason the hero's closing rule sits short.
   Scoped, not on .display: the reference's BOARD heading measures
   b2b/x-height 1.38, a looser setting than the hero's. */
.hero-copy .display{line-height:.93}

/* Insurance. The tracking above already drops min-content below the
   39fr share, so this is not the cure — but it makes a future longer
   word or translated heading spill visibly instead of silently moving
   the split again. */
.hero-copy{min-width:0}

/* The board heading is the worst-set type on the page: x-height 30px
   against the reference's 48-49, block height 76px against 141, and it
   fills only 250px of its 320px measure — it is not even filling its own
   column, so it reads as a subhead where the reference has a second
   display statement.
   The binding case is 901px, the narrowest viewport at which the board
   is still three columns: there the intro measure is 264px (with the
   column fix below) and 4.95vw gives 44.6px, putting "wants that, too."
   at 256px with 8.6px of slack. At 1190 that is 58.9px -> 338px of ink
   in a 359px measure, against the reference's 352 in ~364.
   letter-spacing is inherited from .display and is load-bearing here:
   without it this string overruns the measure and wraps to four lines.
   line-height 1.0 (not the inherited .86) matches the reference's own
   looser board setting: b2b/x-height 1.37 vs the measured 1.38. */
.board-intro .display{
  font-size:clamp(32px,4.95vw,72px);
  line-height:1;
}

/* The strip carries the same fault in uppercase. Measured "ONE LINE":
       ref   O17 N19 E15 / L13 I7 N18 E14   gaps 2,1,2,2,3   cap 44
       build O17 N17 E14 / L14 I7 N17 E15   gaps 3,3,2,3,3   cap 35
   Same glyph widths at a 26% smaller cap, and gaps 0.8px wider each.
   -.018em removes exactly that 0.8px, landing on the reference's 2.0px.
   Do NOT also raise the size: I swept it, and 'SEE WHAT HAPPENS' has
   only 217px of cell at 901px, which caps the type at ~31.6px against
   the 30.6px it is already set at. Anton's uppercase fills that column
   at any size that fits. See the note on cap height in "close enough". */
.strip-item h2{letter-spacing:-.018em}


/* ── 3. The hero photograph and its captions ───────────────────────────
   The reference breaks the cafe photograph 48px ABOVE the hero's closing
   rule (photo's last row y=744, paper from y=745, rule at y=793) and
   sets "GOOD COMPANY. NO PARTICULAR RUSH." as dark ink on that paper
   band, flush with the photo's left edge. The build runs the photo all
   the way to the rule and burns the caption into it in white over the
   red chair. The band is not decoration — it is the hero's breath before
   it closes, and losing it is why the build's hero reads as heavier at
   the bottom than the mockup's.

   The flex item here is the <picture> wrapper, not the <img>
   (index.html:69-73), so the sizing goes there. aspect-ratio gives it an
   intrinsic height that survives into the narrow layout, where
   .hero-art's height is no longer definite; at desktop flex-shrink
   trims it to whatever the 48px band leaves. 7 + (10px x 1.7) + 24 = 48. */
.hero-photo{height:100%;display:flex;flex-direction:column}
.hero-photo picture{display:block;flex:1 1 auto;min-height:0;aspect-ratio:1/1}

.caption-under{
  position:static;
  flex:0 0 auto;
  margin:7px 0 24px;      /* left:0 — the reference's caption is flush with the photo edge at x=464 */
  color:var(--ink-soft);  /* measured rgb(95,72,74) in the reference; --ink-soft renders rgb(104,78,84) */
  text-shadow:none;
}

/* The lower-right caption is CLIPPED: "CONVERSATIONS" renders as
   "CONVERSATIO", running to x=1189, the last pixel of the viewport, with
   html{overflow-x:clip} swallowing the rest so there is not even a
   scrollbar to hint at it. The reference's text ends at x=1177 with 13px
   of clear paper. Cause: an 84px column minus a 34px right gutter leaves
   a 50px box for a ~98px string.
   The paper block's own width needs no change — clamp(240px,48%,366px)
   resolves against .hero-art, and once the 39/61 split is restored above
   that is 348px, putting the block at x=842 against the reference's 840.
   A 96px caption column leaves the street inset at 230px ending at
   x=1082, where the reference's ends at 1083.
   The reference sets this caption tighter than the top-right one — same
   7-8px cap, but "DIFFERENT" measures 52px here against 65px up there —
   so opting out of the shared .17em label tracking is faithful, not
   invention. 9.5px/.03em gives a 5.91px glyph pitch against the
   reference's measured 5.875; "CONVERSATIONS" comes to ~76px in an 83px
   box. white-space:normal is not what fixes the clip (the lines are hard
   broken with <br />) — it is there so a longer translated phrase wraps
   instead of silently overflowing again. */
.hero-corner{grid-template-columns:1fr 96px}
.caption-br{
  margin:0 13px 6px 0;
  font-size:9.5px;
  letter-spacing:.03em;
  line-height:1.5;         /* 14.25px vs the reference's measured 14.6 */
  white-space:normal;
}


/* ── 4. The board ──────────────────────────────────────────────────────
   Three equal 1fr tracks, with 34px of padding and a border placed
   INSIDE the third one, so column 3's content box is 316px against
   column 2's 352px. Because the banners are aspect-ratio locked, the
   third banner comes out 134px tall against 149px, and the city/days
   row, the line and the answer link all sit 15px higher than their
   neighbours. In the reference both banners are 347x148 and everything
   registers. The rules also land hard against the left of each gap
   (x=384, x=805) instead of centred in it (reference x=421, x=796).

   Moving the rules into the gaps as pseudo-elements costs the tracks
   nothing. 1.07fr matches the reference's wider intro column; the 28px
   gap is the reference's own (its banner 2 ends x=781, banner 3 starts
   x=809). padding-right:12px is what lands the intro's content at
   x=393.5 — exactly where the reference's city dropdown border sits.
   The pseudo-element is offset from the PADDING box, whose right edge
   padding-right does not move, so it stays centred in the gap.
   Verified: rules at x=419 and x=795, both banners 347.2 x 147.8. */
.board{grid-template-columns:1.07fr 1fr 1fr;gap:0 28px}

.board-intro{position:relative;padding-right:12px;border-right:0}
.board-intro::after{
  content:'';position:absolute;top:0;bottom:0;right:-14px;width:1px;
  background:var(--rule-faint);
}

.line{position:relative}
.board-lines .line + .line{padding-left:0;border-left:0}
.board-lines .line + .line::before{
  content:'';position:absolute;top:0;bottom:0;left:-14px;width:1px;
  background:var(--rule-faint);
}

/* The words on the board are the most important text in the section and
   are set 26% small: measured on the shared words, 'Someone' is 116px in
   the reference against 92px in the build, 'turns' 65 against 50. 2.2vw
   gives 26.18px and puts 'Someone' back on 116px. The 18px floor is
   deliberate — the mockup is desktop-only and raising the floor would
   push the narrow layout from two lines to three.

   And the reference draws a full-measure hairline between each line and
   its answer link, at y=1229 across both example columns and above
   'BROWSE BY CITY' in the intro — one horizontal register shared by all
   three columns. The build has nothing there, so the quote runs straight
   into its call to action. */
.line-body{
  margin:0 0 15px;
  padding-bottom:20px;
  border-bottom:1px solid var(--rule-faint);
  font-size:clamp(18px,2.2vw,27px);
  line-height:1.28;       /* 34px reference leading on 26.18px */
}

/* The EXAMPLE badge lives INSIDE .line-body, so it counts toward the
   height the new rule hangs off. Left inline it fits on the text's last
   line in one column and wraps to its own line in the other, dropping
   that column's rule ~29px — and which column wraps changes with
   viewport width and with the French and Spanish copy. Block-level makes
   the two columns identical at every width. */
.is-example .line-body::after{
  display:block;
  width:max-content;
  margin:13px 0 0;
}


/* ── 5. Supporting copy ────────────────────────────────────────────────
   Hero body: the reference sets two lines, the build three with
   'answers.' orphaned. Measured on the shared words, the reference is
   330px against the build's 301 — Inter at 17px, not 15.5. But size
   alone does not fix it: the binding measure was max-width:34ch
   (Inter's '0' is .631em, so 332px), and at 17px that is still only
   365px against the 386px the first sentence needs. 24em = 408px sits
   just above the 396px column, handing the measure back to the column at
   the design width. Leading was already correct in absolute terms
   (15.5 x 1.52 = 23.6px against the reference's 24), so the ratio comes
   DOWN as the size goes up: 17 x 1.41 = 23.97. */
.hero-body{font-size:17px;line-height:1.41;max-width:24em}

/* The small supporting line is uppercased and letterspaced by CSS into a
   system label. The HTML is already correct sentence case; style.css:43
   sweeps .fineprint into the shared uppercase label group and :112 adds
   .13em on top. In the reference it is quiet sentence-case body text —
   240px for 42 characters against the build's 294px, 14px
   ascender-to-descender. Keep --ink-soft: calibrated against text on the
   same image that is definitively full oxblood (eyebrow mean-darkest
   rgb(37,14,18), hero body rgb(40,17,22)), the reference fineprint reads
   rgb(84,66,62) — muted, not oxblood. All four properties are re-stated
   because this rule has to out-rank the label group by source order. */
.fineprint{
  font-size:12.5px;
  font-weight:400;
  text-transform:none;
  letter-spacing:0;
  line-height:1.45;
}

/* The first line of type on the page stops 54px short of the reference's
   (217px against 271px) — and it is both size and tracking, not tracking
   alone: total glyph ink measures 138px against 156px, cap height ~8.1
   against ~9.4. Generous label tracking is a stated brand trait, so this
   one is worth setting apart from the shared 10px/.17em. 11px x .27em
   predicts 270.6px against the measured 271. Scoped to .hero-copy, so
   the board and composer eyebrows are untouched. */
.hero-copy .eyebrow{font-size:11px;letter-spacing:.27em}

/* The board intro paragraph breaks to four lines with 'conversation.'
   orphaned; the reference has three. max-width:31ch resolves to 293px,
   14px short of the 307px the reference's second line needs. 20.5em
   (318px) sits inside the reference's own measure and holds its exact
   three-line break; 15.5px puts line 1 on 287px against the measured
   289, and 1.42 x 15.5 = 22.0px, the reference's measured 22px leading. */
.board-body{font-size:15.5px;line-height:1.42;max-width:20.5em}


/* ── 6. Masthead ───────────────────────────────────────────────────────
   The wordmark's ink measures 68 x 17 against the reference's 153 x 35 —
   less than half. In a 59px masthead it reads as a favicon. The PNG is
   900x252 with the ink occupying 88.1% of the box height, so a 40px box
   yields 35.2px of ink.
   display:block removes the inline baseline gap, which otherwise
   swallows most of any vertical offset; align-self:start + 5px then
   places the ink top at y=9 — the reference's optically-high position,
   not centred. Header rule stays at y=58. */
.wordmark{align-self:start;margin-top:5px}
.wordmark img{height:40px;width:auto;display:block}


/* ── 7. Narrow viewports ───────────────────────────────────────────────
   MUST stay after the desktop rules above: media queries add no
   specificity, so .board and .hero-corner have to be re-stated here or
   the desktop values would win at every width.

   Today at 500px the street inset renders as a 48px thumbnail in a 240px
   paper panel, one caption is sliced mid-word by that panel ("NO
   PARTICULAR RUS") and another by the viewport edge. The whole existing
   hero-art block in @media(max-width:900px) is inert: it sets
   right/bottom/left on .hero-inset and .caption-br, which are static
   grid children of .hero-corner, so only `width:36%` takes effect — and
   it takes effect as 36% of an already-narrow track.
   The brief names the remedy: "place it directly after the hero photo...
   Ensure tiny captions remain readable." */
@media(max-width:900px){
  .hero-art{aspect-ratio:auto}        /* the corner block now needs real height below the photo */
  .hero-photo{height:auto}

  .hero-corner{
    position:static;z-index:auto;
    width:auto;max-width:430px;       /* keeps it a "smaller controlled" inset, not a full-width slab */
    padding:16px var(--gutter) 24px;
    grid-template-columns:minmax(0,1fr) 96px;
    gap:14px;
  }
  .hero-inset{width:auto;max-width:none}   /* neutralises the inert width:36% at :290 */
  .caption-under{margin:10px var(--gutter) 0}  /* the photo is full-bleed here, so it needs the gutter */

  .board{grid-template-columns:1fr;gap:34px}
  .board-intro{padding-right:0}
  .board-intro::after,
  .board-lines .line + .line::before{display:none}  /* .board-lines is a flex column here */
}


/* ── 8. Optional: the full stop in 'coffee.' ───────────────────────────
   Skippable. This is the one item that fabricates a glyph rather than
   correcting a value, and the page ships fine without it.
   Measured: the reference's stop is 30w x 33h with curvature on all four
   edges (fitting its row-width profile gives a superellipse exponent
   ~2.55); Anton's is a 23 x 20 rectangle with zero corner antialiasing —
   under half the visual mass, in the largest single area of flat colour
   on the page. Requires the markup change below in all three locales.
   No margin: at the -.035em set above, Anton's 'e' sidebearing leaves a
   2.8px gap, and the reference's measures 3px. */
.display .stop{
  display:inline-block;
  width:.223em;                /* 30.0px at the rendered 134.5px */
  height:.245em;               /* 32.9px — the reference's dot is taller than it is wide */
  vertical-align:baseline;     /* the reference dot's bottom sits on the baseline, as does Anton's period */
  background:currentColor;     /* -> var(--tomato), from .display em */
  border-radius:43%;           /* fitted: 43% gives 0.75px mean error, 38% reads square, 50% too round */
}

/* =====================================================================
   9. THE MOBILE PAGE — 320px to 900px
   Append at the END of style.css. Media queries add no specificity, so
   every rule here beats the one it supersedes on source order alone.

   WHY PLAIN vw IS EXACT HERE.
   --gutter is clamp(18px,2.9vw,34px) and 2.9vw only passes 18px at a
   620.7px viewport, so below that the measure M is exactly 100vw - 36px
   and every "k·vw - c" below is an identity, not a fit. Each display cap
   engages between 435 and 440px, i.e. inside the band where that is true.

   FONT ARITHMETIC — re-derived from the shipped files with fontTools,
   not taken from the brief. Anton (upem 2048, x-height 1500 = .7324em,
   cap 1760 = .8594em) at the -.035em style.css:423 sets on .display:
       "another"          adv 2.8790em   ink right 2.9062em   <- binds h1
       "Stay for"         adv 2.7888em   ink right 2.8160em
       "coffee."          adv 2.5084em   ink right 2.5166em
       "wants that, too." adv 5.7291em   ink right 5.7372em   <- binds h2
       "Vous cherchez quoi, au juste ?"  ink right 11.2614em  <- binds the
                                            composer title (longest locale)
   and at the -.018em style.css:471 sets on the strip:
       "SEE WHAT HAPPENS" adv 6.8570em   ink right 6.8560em   <- binds
   Inter, instanced at each weight:
       "CONVERSATIONS"                    109.53px @10px/.17em/600
       "GOOD COMPANY. NO PARTICULAR RUSH."  262.29px @10px/.17em/600
       eyebrow en/fr/es @10px/.18em       223.7 / 280.1 / 303.3px
       CTA en/fr/es @13px/600 incl. box   148.0 / 173.0 / 152.2px
   The fallback arrow (U+2197 is outside both @font-face unicode-ranges)
   measures 12.22px at 13px — read off /tmp/mobile-full.png, where the
   masthead button is exactly 148px wide, as 36+91.78+8+12.22 predicts.

   Every h1/h2 line breaks on a hard <br />, and the h1, the board
   heading, the strip and both example lines are English in /fr/ and /es/
   as well, so the binding words above bind in all three locales.
   ===================================================================== */


/* ── 9.0 Four faults that are not width-scoped ─────────────────────────

   (a) .display-sm is applied at index.html:103 and :173 (and in /fr/ and
   /es/) and grep finds it in style.css zero times, so the composer title
   falls through to the UA's h2{font-size:1.5em} = 22.5px: the brand's
   display face, set smaller than the hero body text, at the moment of
   highest intent. A global .display-sm rule would be dead on arrival —
   both elements carrying the class are also matched at (0,2,0), by
   .board-intro .display and by the rule below — so only the scoped one
   is written. THIS CHANGES THE DESKTOP MODAL TOO, from 22.5px to 36px.
   That is correct, but it is a change to an approved page: say it out
   loud before shipping.
   Fit: the French "Vous cherchez quoi, au juste ?" is the longest of the
   three at 11.2614em, so 7.6vw holds it on one line from 320px up
   (24.3 x 11.2614 = 274px in a 284px measure) and the 24px floor binds
   only below 316px. At the 36px cap it is 405px in the desktop dialog's
   460px measure. */
.composer .display-sm{font-size:clamp(24px,7.6vw,36px);line-height:1;margin-bottom:20px}

/* (b) #when-input (index.html:191, fr:195, es:195) carries NO type
   attribute, and an attribute selector matches the attribute, not the
   element's default — so style.css:242 has never styled it. It renders
   as a raw 13.3px Arial OS control in a form of Inter fields on paper
   with #918078 hairlines, and at 13.3px it is also the page's worst iOS
   zoom trap. Fixed here in CSS for all three locales; the two-character
   markup fix is worth doing as well. Supersedes :242. */
.composer-form input:not([type]){
  width:100%;border:1px solid var(--rule);background:#F7F4EA;color:var(--oxblood);
  padding:13px 14px;font:inherit;outline:none;
  transition:border-color var(--t-control) var(--ease);
}
/* (0,3,1), so it still beats the rule above. Scoping the whole fix to the
   untyped input is also what keeps it OFF the textarea: sweeping `textarea`
   into the selector above would re-apply `font:inherit` after style.css:247
   and silently drop the one field this dialog exists for from 17px to 15px. */
.composer-form input:not([type]):focus{border-color:var(--tomato)}

/* (c) THE BRAND RED FAILS AS SMALL INK. Measured: #CE4730 on #EFEBDD is
   3.852:1, so .answer (13px/600 — the board's whole call to action),
   .index (10px) and .cp-live all miss 1.4.3's 4.5:1. The answer is not a
   new colour: #B93B26 is already in the palette as the CTA's pressed
   state (style.css:401) and measures 4.735:1 on paper, 5.135:1 on the
   #F7F4EA fields. At 10-13px it reads as the same red.
   The true tomato stays everywhere it passes: "coffee." (display type,
   needs 3:1), the CTA fill (white on tomato is 4.597:1), the 1px rules
   and the selected-row inset (non-text, need 3:1).
   Global, not mobile-scoped — the failure is the same on desktop. */
:root{--tomato-ink:#B93B26}
.index,.answer,.cp-live{color:var(--tomato-ink)}
.quiet-link:hover,.colophon nav a:hover,.lang-switch a:hover{color:var(--tomato-ink)}

/* (d) A metric-matched fallback for the display face. font-display:swap
   means the fallback is painted on every first view, and doubling the
   heading turns a graceful degradation into a clipped one: Anton's
   "another" is 3.124em raw, Helvetica's is 3.391em, so at 119px the
   unadjusted fallback overruns a 354px measure by 40px on a line that
   cannot reflow (hard <br />). 88% keeps it at 2.769em against Anton's
   2.879em — narrower than the real face, never wider. */
@font-face{
  font-family:'Anton fallback';
  src:local('Haettenschweiler'),local('Arial Narrow'),local('Helvetica Neue'),local('Arial');
  size-adjust:88%;ascent-override:118%;descent-override:33%;line-gap-override:0%;
}
:root{--display:'Anton','Anton fallback','Haettenschweiler','Arial Narrow',sans-serif}

/* iOS inflates type in landscape, and paints a translucent ROUNDED grey
   rectangle over every tap — including the square tomato CTA, which
   contradicts the brand's first rule on every single press. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{-webkit-tap-highlight-color:rgba(206,71,48,.18)}


/* ── 9.1 The stacked page (<=900px) ───────────────────────────────────
   Live wherever .hero is a single column, which style.css:286 makes it
   at 900px. */
@media(max-width:900px){

  /* Safe areas. These are inert today — the viewport meta stays at
     viewport-fit=auto, so every env() below resolves to 0 and the UA
     keeps the layout viewport clear of the notch on its own. They are
     here so that adding viewport-fit=cover later cannot silently run the
     masthead, the headline and the colophon under the hardware in
     landscape, which is exactly what happens on an 852x393 iPhone —
     inside every query in this file — the moment cover switches the UA's
     inset off on all four edges. One token carries it everywhere
     --gutter is already used. */
  :root{
    --gutter:max(clamp(18px,2.9vw,34px),
                 env(safe-area-inset-left,0px),
                 env(safe-area-inset-right,0px));
  }
  .masthead{padding-top:env(safe-area-inset-top,0px)}

  /* THE ONE RULE. The brief's central responsive instruction is "scale
     the display type deliberately, keeping it much more prominent than
     the body", and the display type IS the brand. Today it is not
     scaled, it is floored: clamp(58px,11.3vw,178px) (style.css:107)
     needs a 513px viewport before 11.3vw clears 58px, so /tmp/hero360.png
     and /tmp/hero430.png are pixel-identical through the heading and the
     fill gets WORSE as the phone gets bigger — 51.9 / 47.5 / 42.6% of the
     measure at 360/390/430 against 99.7% in the reference.
     Size it off the word that binds instead. 33.6% of the measure puts
     "another" at 33.6 x 2.9062 = 97.6% of it, at EVERY width:
         320 -> 95.4   360 -> 108.9   375 -> 113.9
         390 -> 118.9  412 -> 126.3   430 -> 132.4
     2.05x today, with a flat 2.4% of clear paper (6.8px at 320, 8.4px at
     390) so html{overflow-x:clip} never does load-bearing work.
     x-height:measure becomes .7324 x .336 x 2.9062 = .246, against the
     desktop build's own .249.
     The 134px cap is the desktop page's rendered display size, reached at
     a 434.8px viewport: the largest phone grows until its headline equals
     the desktop headline, then stops. Supersedes style.css:107. */
  .hero-copy .display{
    font-size:min(calc(33.6vw - 12.1px),134px);
    margin-bottom:.11em;     /* in em, so the gap belongs to the type and not to a breakpoint */
  }

  /* And the column stops growing where the type does. Above the 134px
     cap the measure keeps widening and the headline would flatline at
     46% fill by 900px — the one view where the page stops being the
     publication. 400px of measure is 97.4% fill, and the cap
     self-engages at the same 435px viewport the type's does, so this is
     inert on every phone. An editorial page does not chase a wide
     column; it lets the column stop. */
  .hero-copy{
    padding:38px var(--gutter) 34px;    /* 30px bottom at :287 — the closing band grows with the type */
    max-width:calc(400px + var(--gutter) * 2);
  }

  /* RHYTHM. The air was sized for a 58px heading; at 119px the same
     constants read as a default stylesheet. Retargeted to the
     reference's own gap-to-h1-block ratios now that the h1 block goes
     from 162px of ink to 332px at 390. The 38px padding-top is
     deliberately not in this list: it measures 41px to the eyebrow,
     which is the reference's .123 exactly. */
  .hero-body{margin-bottom:22px}                  /* was 26px :110 */
  .hero-actions{gap:14px 18px;margin-bottom:18px} /* was 22px :111; the row gap is for the French CTA, which wraps at 320 */

  /* The eyebrow is 11px/.27em (style.css:633) because that is what the
     reference measures in a 1122px masthead. In a 354px measure the same
     tracking runs the French to 343.7px and the Spanish to 372.2px, so
     two of the three locales set the first line of the page as a
     two-line paragraph above the headline. 10px/.18em is 223.7 / 280.1 /
     303.3px — one quiet rule of tracked caps in French from 320px and in
     Spanish from 340px — and it holds the reference's own eyebrow:h1
     ratio (desktop 11/134.5 = .082; mobile 10/118.9 = .084). */
  .hero-copy .eyebrow{font-size:10px;letter-spacing:.18em;margin-bottom:12px}


  /* ── The hero photograph ───────────────────────────────────────────
     THE STREET INSET GOES BACK INTO THE CORNER. What ships is neither of
     the brief's two options: measured in /tmp/mobile-full.png the inset
     renders 244 x 264 — its full desktop size, on a 390px phone, 63% of
     the page — inside a 332px slab whose right column is 96px of
     near-empty paper, and the hero becomes three full-width rectangles
     in a column. That is the most ordinary arrangement available and
     precisely why the page reads as a website. The corner bite is the
     only deliberate asymmetry the hero owns, and on a phone it is worth
     MORE, not less, because there is no two-column split left to carry
     it.
     It is free. The plate is exactly 390x390 at y=538-927 in the
     capture; the couple's faces and the man's hand end at 47% of the
     frame; and the block's footprint from 54% down has a mean luminance
     of 37, so the paper lands on a reliably dark ground exactly as it
     does on desktop. And it is shorter: hero-art goes ~738px -> ~504px
     at 390.

     GEOMETRY. The pull-up is derived, not guessed: the inset's height is
     (blockW - 14px - gutter) x 260/240, so subtracting that plus the
     12px paper margin lands the inset's bottom edge exactly ON the
     photograph's bottom edge at every width and in every locale. A
     constant -44vw (as first specified) knows neither the inset's height
     nor the caption's line count and overhangs the photo by 11-42px on
     phones while stopping 69px short at 900 — an 11px overhang reads as
     a mistake, where a flush edge reads as a bite. Resulting block top,
     as a fraction of the plate: 54.3% at 320, 58.6 at 360, 58.1 at 390,
     57.6 at 430, 56.0 at 620, 65.0 at 900 — 7 to 18 points of plate
     clear of the faces everywhere, and the CTA is 190px higher, in the
     copy block above the photograph.

     WIDTH. The 44% is the reference's own inset:plate ratio (measured
     off /tmp/reference.png: inset 242 x 260 at x=842-1083, y=517-776, in
     a 726 x 687 plate = 33.3% of its width, 37.8% of its height). This
     lands the inset on 35.8% and 38.8% — the reference's proportions,
     not merely something smaller. The 156px floor is what
     "CONVERSATIONS" (109.53px at the house label spec) needs once the
     block's 14px paper margin and the gutter are taken out; the 320px
     cap stops the inset outrunning its 496px source on a tablet.

     padding-right is the gutter, not 0. With the caption stacked under
     the inset rather than beside it, a 0 right padding would bleed the
     street photograph to the screen edge while its own caption sat 18px
     in — one paper block with two right edges, in a design whose stated
     traits are "square corners, fine rules, strong alignment". At the
     gutter the inset's right edge lands on the page's own right margin
     line, where the masthead CTA, the hero copy, the strip, the board
     and the colophon all end.

     position:relative + z-index is load-bearing: a static block's
     background paints below the figure's replaced content, so without it
     the paper would vanish behind the photograph.
     Supersedes style.css:675-681 and neutralises the grid at :519. */
  .hero-art{aspect-ratio:auto;min-height:0;padding-bottom:26px}
  .hero-photo{position:relative;height:auto}

  .hero-corner{
    position:relative;z-index:2;
    display:block;
    width:clamp(156px,44vw,320px);max-width:none;
    margin:calc(-12px - (clamp(156px,44vw,320px) - 14px - var(--gutter)) * 1.08334) 0 0 auto;
    padding:12px var(--gutter) 0 14px;
    background:var(--paper);
  }
  .hero-inset{width:auto;max-width:none;margin:0}   /* neutralises the inert width:36% at :290 */

  /* Taking the caption out of flow is what makes the pull-up
     deterministic — in flow it sits between the photograph and the block
     (style.css:489-495) and its line count, which changes with width and
     locale, would move the bite. top:100% of .hero-photo is the
     photograph's bottom edge, because the figcaption is now the only
     out-of-flow child and the <picture> is a square.
     And 126px is chosen, not inherited. The natural measure left of the
     block is 174px at 390, and at any measure between 133.5 and 262.3px
     the greedy break is "GOOD COMPANY. NO / PARTICULAR RUSH." — it hangs
     "NO" off the first line and splits the second sentence.
     text-wrap:balance does NOT fix that: balance minimises the widest
     line, and the greedy pair maxes at 133.5px against the alternative's
     147.5px, so balance keeps the orphan. Measured widths: the full
     string 262.29, "GOOD COMPANY." 110.62, "NO PARTICULAR" 103.70,
     "GOOD COMPANY. NO" 133.52, "NO PARTICULAR RUSH." 147.45.
     A 126px measure breaks it "GOOD COMPANY. / NO PARTICULAR / RUSH." at
     every phone width — three lines of tracked caps answering the
     caption-br's four across the same band — with 15px of slack on line
     one and 7.5px before line one would take "NO". The min() keeps a
     constant 26px of clear paper between caption and block below 320px,
     where the block's floor binds. */
  .caption-under{
    position:absolute;top:100%;bottom:auto;left:var(--gutter);right:auto;
    margin:10px 0 0;
    max-width:min(126px,calc(100vw - clamp(156px,44vw,320px) - 44px));
  }

  /* The 9.5px/.03em at style.css:520-526 is a desktop-only concession —
     the comment there says so: it exists to fit CONVERSATIONS into an
     83px column at 1190px. Inside the corner block the measure is 124px
     at 320 and 140px at 390, where the house label spec fits (109.53px;
     the string is English in all three locales). At 9.5px it was the
     only type on the page under 10px and it silently opted out of the
     .17em every other label shares. overflow-wrap is the text-zoom
     guard: at Android's 200% font scale CONVERSATIONS is one unbreakable
     219px word in a 140px box, and breaking it is better than clipping
     it into html{overflow-x:clip}. */
  .caption-br{
    margin:10px 0 0;
    font-size:10px;letter-spacing:.17em;line-height:1.7;
    white-space:normal;overflow-wrap:anywhere;
  }

  /* "SAME CITIES / DIFFERENT PEOPLE" is deleted outright below 900px by
     style.css:289. The brief says "ensure tiny captions remain readable,
     OR simplify their placement" — deleting one of the hero's two
     overlay captions is neither, and these captions are half of what
     makes the hero read as a spread rather than a header image. It is
     free: absolutely positioned, so zero page height.
     What it cannot keep is the desktop offset. On the 726px desktop
     plate a 74px caption sits in the far-right 10%, entirely inside the
     dark door jamb; on a 390px plate the same 74px reaches 19% in, into
     the lit window. I rasterised the four lines from the shipped Inter
     and sampled contrast over the INKED pixels only (white at .82 alpha,
     over a background carrying the element's own text-shadow, modelled),
     at 320/360/390/430:
         top:26px  8.6 / 12.6 / 10.4 / 10.0% of ink below 4.5:1,
                   floor 2.05 / 1.79 / 1.90 / 1.81
         top:18vw  0.0 /  0.0 /  0.4 /  0.2%,
                   floor 5.00 / 6.46 / 3.04 / 3.65
     A mean would have passed the first one; contrast is per glyph.
     18vw, not 18px: the plate is 100vw square, so a vw offset is the
     same normalised point on the photograph at every width, which is why
     one measurement holds for all of them. It lands in the doorway below
     the man's hair, 38px clear of the corner block's top edge at 320 and
     more everywhere else. Supersedes :289. */
  .caption-tr{display:block;top:18vw;right:var(--gutter);max-width:74px}


  /* ── The three-part strip ──────────────────────────────────────────
     Stacked from 900, not from 620. Below 900 .hero and .board are both
     single-column (style.css:286, :685), so in the 621-900 band the
     strip is the only three-up element on an otherwise stacked page —
     which is what makes a tablet screenshot read as an unfinished
     desktop. Three rows is also the only reflow that survives: a
     3-across grid gives 118px per cell at 390 and wraps "SEE WHAT
     HAPPENS" to three lines, which is the illegibility the brief
     forbids; 2+1 breaks the equality of three steps that are a sequence;
     a scroller hides step 03 behind a gesture the page uses nowhere
     else. Rotating the register 90 degrees keeps every property the
     desktop strip has — equal cells, one ruled band, numbered,
     hairline-split — and a contents page is what an independent magazine
     does with a strip like this.
     And then SIZE it. clamp(26px,3.4vw,44px) (style.css:159) needs a
     765px viewport, so the strip sits on its floor: "ONE LINE" measures
     78.5px of ink in a 354px measure — 22% — where the reference fills
     288 of 298px. 0.36 of the hero holds the reference's own strip:hero
     relationship (measured 51.2/134.5 = .381, compressed slightly so
     320 still clears), i.e. .124M = 12.4vw - 4.5px:
         320 -> 35.2   360 -> 40.1   390 -> 43.9   430 -> 48.8
     Fit against an 18px index column and a 12px gap: 300.7px of ink in
     324px at 390, 241.2 in 254 at 320. The 50px cap is .36 x 134 and
     engages at 439.5px alongside the other two, so hero : board : strip
     is a flat 1 : .437 : .369 from 320 to 900 against the reference's
     1 : .438 : .381. Rows go 57px -> 80px. Supersedes :306-308 and :159. */
  .strip{grid-template-columns:1fr}
  .strip-item{min-height:0;padding:18px var(--gutter);gap:12px;align-items:center}
  .strip-item + .strip-item{border-left:0;border-top:1px solid var(--rule-faint)}
  .strip-item h2{font-size:min(calc(12.4vw - 4.5px),50px);line-height:1}

  /* A fixed column so the three phrases align on one edge — "01" is
     14.2px and "03" is 16.4px, so without it they do not. In em, not px,
     so it survives text-only zoom: 1.8em is 18px at the label's 10px and
     grows with it. margin-top:0 neutralises style.css:156, which was
     tuned to a 44px cap height; without it the index's cap top sits at
     3.9px against Anton's 2.8px, which is the same optical line. */
  .index{flex:none;width:1.8em;align-self:flex-start;margin-top:0}


  /* ── The board ─────────────────────────────────────────────────────
     THE SECOND DISPLAY STATEMENT. Same frozen floor, one section down:
     clamp(32px,4.95vw,72px) (style.css:458) needs a 647px viewport, so
     the board heading is 32px on every phone — 184px of ink in a 354px
     measure, 52%, where the reference fills 94% of its column. Its ratio
     to the hero is wrong in the other direction too: 32/58 = .55 today
     against the reference's 58.9/134.47 = .438.
     .4375 x (M/2.9062) = .147M = 14.7vw - 5.3px, a flat 84.3% fill —
     comfortable, because "wants that, too." is 5.7372em and does not
     have to fill the way one word does.
         320 -> 41.7   360 -> 47.6   390 -> 52.0   430 -> 57.9
     52.0/118.9 = .437. The 59px cap is .4375 x 134 and engages at 437px
     alongside the hero's. line-height 1 is the reference's own looser
     board setting (the comment at :456), not the .93 on the hero.
     Supersedes :458 and :171. */
  .board-intro .display{
    font-size:min(calc(14.7vw - 5.3px),59px);
    line-height:1;
    margin-bottom:.3em;     /* was a flat 18px :171 — scales with the heading now */
  }

  /* The same column cap as the hero, applied as padding so the intro's
     closing hairline still runs the full measure — a magazine sets its
     rules to the measure and its text to a column. Inert below a 436px
     viewport, so no phone sees it. */
  .board-intro{padding-right:max(0px,calc(100% - 400px))}

  /* 20.5em (style.css:641) is a desktop measure-fit: 318px, stopping
     36px short of the column it now has to itself. */
  .board-body{max-width:min(100%,26em)}

  /* The words on the board are, per the comment at style.css:562, "the
     most important text in the section", and clamp(18px,2.2vw,27px)
     (:578) needs an 818px viewport to move — so they render at 18px on a
     phone against 26.18px on desktop, in a banner of ALMOST EXACTLY THE
     SAME WIDTH (354px mobile against 347px desktop). Same object, same
     treatment: 7.3% of the measure is the desktop ratio, landing on
     25.8px at 390 and capping at the desktop 27px from 406px up; the
     20px floor binds only below 310px. Both example lines stay three
     lines at every phone width, as they are on desktop — the full string
     is 31.4536em in Inter, so 813px over a 354px measure at 390 and
     653px over 284px at 320. */
  .line-body{font-size:clamp(20px,calc(7.3vw - 2.6px),27px)}

  /* Same fault, same physical object: the scrawl is 12px on a 354px
     mobile banner where desktop sets 14.28px on a 347px one — 18% small
     in proportion. 4.11% of the measure is the desktop ratio exactly.
     What does change is the box. At max-width:40% the shrink-to-fit
     block straddles the shelf/wall edge, which on the bookshop banner
     sits at x=250 of 354, so the longest line starts over the books:
     26% and right:4% keep it on the pale wall, where #4a3f38 measures a
     median 3.84:1. It stays there deliberately — this is handwriting
     recreated from the photograph, aria-hidden="true" at index.html:142,
     and darkening it to caption contrast would stop it reading as
     pencil on a wall. */
  .scrawl{font-size:clamp(12px,calc(4.11vw - 1.5px),16px);right:4%;max-width:26%}

  /* .city-control .cp{max-width:330px} (style.css:351) is a desktop
     sidebar cap left behind in a stacked column: it stops the trigger
     64px short at 430 while the BROWSE BY CITY label and the hairline
     above it run the full measure. It is the only element in the board
     that does not register with the rules that label it. The column cap
     above now does the capping above 436px, so this can simply go.
     display:block is not cosmetic — see #use-location below. */
  .city-control .cp{display:block;max-width:none}

  /* "Use my location" is a 112 x 19.5px text button sitting under a 50px
     bordered field: two adjacent targets, one of them under half the
     touch minimum, and visually an orphan. margin-top:-1px is meant to
     collapse the two borders into one ruled control — but .cp is
     display:inline-block (style.css:322) with no in-flow line boxes of
     its own, so its baseline is its bottom margin edge and the parent's
     strut contributes its full descent below it: at the inherited 15px/1.5
     with Inter's hhea descent of 494/2048 that is 3.62 + 2.18 = 5.79px of
     paper, of which -1px removes a sixth. display:block on .cp above
     kills the line box, and then -1px collapses the borders exactly, at
     every font size and in every locale.
     The [hidden] guard matters: script.js:456 sets loc.hidden = true on a
     device with no geolocation, and an author display:flex would
     otherwise beat the UA's [hidden]{display:none}. */
  #use-location{
    display:flex;align-items:center;width:100%;min-height:48px;
    margin:-1px 0 0;padding:0 14px;
    border:1px solid var(--rule);background:#F7F4EA;text-align:left;
  }
  #use-location[hidden]{display:none}

  /* The colophon is the page's only centred block (style.css:296-298), which
     is what makes the bottom read as an ordinary stacked website after a page
     of left-flush columns. The ruled two-column index below is a touch
     treatment and stays at <=620; the alignment is an identity fault at every
     stacked width. */
  .colophon{text-align:left}
  .colophon nav{justify-content:flex-start}
  .colophon-meta{text-align:left}
}


/* ── 9.2 The flag and the edition line (<=760px) ──────────────────────
   760, and the number is measured rather than chosen. The desktop
   masthead needs wordmark 142.86 + 26 + nav + 26 + switcher 167.35 + 20
   + CTA of content: 677.7px in English, 671.5 in Spanish and 703.4 in
   French, whose "Écrivez votre ligne" button is 173.0px against the
   English 148.0. Available is 100vw - 2 x gutter = .942 x vw in that
   band, so French clears only from 746.7px up. At 720 — the first
   candidate — French overruns by 23px and Spanish by 2px, and
   html{overflow-x:clip} (style.css:26) swallows the evidence. At 761px
   the measure is 716.9px against French's 703.4, with 13.5px to spare. */
@media(max-width:760px){

  /* THE FLAG. The brief says "keep the wordmark and a compact primary
     action in the header", so shedding the nav is right — but the
     language switcher currently DISAPPEARS (style.css:365) rather than
     moving, which leaves a French speaker who lands on / from a shared
     link with no route anywhere in the rendered document to /fr/: the
     only pointers are <link rel="alternate"> in <head>, which is for
     crawlers. Three locales are the positioning of this product, and the
     board's own two examples are Québec City and Montréal.
     It cannot go inline: the switcher measures 167.35px and at 390 the
     wordmark and CTA already take 279 of a 354px measure. So it takes a
     thin second row under its own hairline, which is more editorial than
     a cramped inline switcher anyway — it reads as a magazine's edition
     line. display:contents promotes it and the CTA out of
     .masthead-right so both can be placed on the masthead's own grid.
     Supersedes :302-304 and :365. */
  .masthead{
    grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto;
    align-items:center;min-height:0;column-gap:10px;row-gap:0;
  }
  .masthead-nav{display:none}    /* #idea and #board are this page, one scroll away, and both are in the colophon */
  .masthead-right{display:contents}

  /* The CTA does not reach the right gutter and the error GROWS with the
     screen — I measured the button at x=198..345 in /tmp/mobile-full.png,
     27px short of the 372px gutter line at 390 — because `auto auto`
     (style.css:302) gives two auto tracks an equal share of the free
     space, so half of it lands in an invisible gap inside .masthead-right.
     Every other element on the page lands on x=18 and x=W-18; the
     masthead is the one band that misses, and it is the first thing on
     the page. A 1fr first track absorbs all of it. */
  .masthead .btn-accent{
    grid-column:2;grid-row:1;align-self:center;
    min-height:44px;               /* was 41.5px — under the touch minimum, on the primary action */
    padding:10px 14px;white-space:nowrap;
  }

  /* The wordmark is DISTORTED at 320px and nobody has seen it, because
     every capture starts at 360: height:40px (style.css:654) is fixed
     while img{max-width:100%} (:32) clamps the width, so once the track
     shrinks the mark is squashed non-uniformly — worst in French, which
     has the longest CTA. Locking the ratio and driving the WIDTH cures
     it for good, and minmax(0,1fr) above lets the track shrink so
     max-width:100% can do its job instead of overflowing the page.
     Measured fit at 320 with the French CTA: 96 + 10 + 173 = 279 in a
     284px measure. The 96px floor binds below 320px and the 132px cap
     from 440px, where the mark's ink paints 122 x 33. */
  .wordmark{
    grid-column:1;grid-row:1;align-self:center;
    display:flex;align-items:center;min-height:44px;margin:3px 0;
  }
  .wordmark img{width:clamp(96px,30vw,132px);height:auto;aspect-ratio:900/252}

  /* The edition line. Full-bleed so its hairline runs edge to edge like
     every other rule on the page, and 38px rows so the three locales are
     real targets rather than 15px of tracked caps — WCAG 2.2's 24x24
     minimum with room, at 7px less than the 44px an AAA target would
     cost on the page's first band. The " · " text nodes between the
     links are anonymous flex items and centre themselves; > * hits only
     the span and the two anchors. The container's padding is the gutter
     minus the items' own 10px, so the first word still starts exactly on
     the page's left margin line.
     Cost: 39px including the rule. At 11px/.12em uppercase the row
     measures 251px of a 284px measure at 320 — worst case French
     current, 252px — so it fits on the narrowest phone. */
  .lang-switch{
    display:flex;grid-column:1/-1;grid-row:2;gap:0;align-items:center;
    margin:0 calc(var(--gutter) * -1);
    padding:0 calc(var(--gutter) - 10px);
    border-top:1px solid var(--rule-faint);
    font-size:11px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  }
  .lang-switch > *{display:flex;align-items:center;min-height:38px;padding:0 10px}
  /* .lang-switch a carries border-bottom:1px solid transparent (style.css:361)
     and style.css:363 colours it on hover. Inside a 38px flex item that rule
     lands at the bottom of the box rather than under the word — the same
     detached-underline fault the consent links have. The row marks the
     current locale with weight and colour (style.css:364), which is enough. */
  .lang-switch a{border-bottom:0}
}


/* ── 9.3 The phone (<=620px) ──────────────────────────────────────────
   Below here the layout is a single narrow column, controls are operated
   with a thumb, and the composer is the whole screen. */
@media(max-width:620px){

  /* 60px of padding under the last answer link before a 1px rule is the
     single largest accidental gap on the page; and 26 above / 26 below a
     hairline is symmetric air that reads as a default. 22/30 gives the
     rule to the item it introduces — the same asymmetry the desktop
     columns have. Supersedes :168, :292-295. */
  .board{padding:32px var(--gutter) 40px;gap:30px}
  .board-intro{padding-bottom:22px}
  .board-lines{gap:22px}
  .board-lines .line + .line{padding-top:30px}

  /* TOUCH. "Answer this line" is what the board exists for and it is a
     104 x 22.5px strip of text; "Read the board" is 24px tall. Raising
     min-height would drag each element's border-bottom off its baseline
     and wreck the underline, which IS the design — so the hit area grows
     around the ink and not one drawn pixel moves. All three are the last
     element in their block, so the overlay cannot steal a neighbour's
     tap. */
  .hero-actions .underlined,
  .answer,
  .composer-done .underlined{position:relative}
  .hero-actions .underlined::before,
  .answer::before,
  .composer-done .underlined::before{
    content:'';position:absolute;left:-10px;right:-10px;
    top:50%;height:44px;transform:translateY(-50%);
  }

  /* THE CITY CONTROL IS A DESKTOP DROPDOWN ON A PHONE. It opens 290px
     downward from top:calc(100% - 1px) and citypicker.js:170-184 only
     ever adjusts left/right — nothing measures the space below. The
     control sits mid-page, so for the panel to be wholly visible the
     trigger has to be in the top ~56% of the screen; anywhere lower and
     most of a 53-row list is off the bottom edge, with the list's own
     overscroll-behavior:contain stopping the page from following it.
     A sheet cannot open off-screen, is always the full measure (which
     also cures the panel hanging narrower than its own trigger), reaches
     48px rows without becoming absurd, and escapes the dialog that
     currently clips it in the composer.
     TOP, not bottom. citypicker.js:197-198 calls search.focus() on open
     whenever the picker is searchable, and setItems() only drops
     searchable below 9 items — both city pickers carry 52. A fixed
     element is laid out against the LAYOUT viewport, which iOS does not
     shrink for the software keyboard and which dvh does not track, so a
     bottom sheet opens underneath the keyboard its own autofocus raised,
     and Safari cannot scroll a fixed element into the visual viewport.
     Anchored to the top, the search field lands where iOS puts its own.
     The audience picker is three options with no search box
     (citypicker.js:75 hides it) and no autofocus, so :has() lets it keep
     the short sheet it should have.
     No shadow, no rounded corner: a solid paper plane under one hard
     oxblood rule, over the same flat oxblood wash .composer::backdrop
     already uses, painted with a spread box-shadow so it needs no extra
     element and no JS. The existing outside-tap close (citypicker.js:67)
     is still the exit.
     !important is not decoration: place() writes left/right inline.
     Note what is deliberately NOT set here — display. .cp-panel carries
     the hidden attribute (citypicker.js:37, :210) and any author display
     value would beat the UA's [hidden]{display:none} and leave the city
     list standing open on page load. Supersedes :337-338. */
  .cp-panel{
    position:fixed;top:0;bottom:auto;left:0!important;right:0!important;
    width:auto;max-width:none;z-index:90;
    border:0;border-bottom:1px solid var(--oxblood);
    padding:calc(8px + env(safe-area-inset-top,0px)) 0 10px;
    box-shadow:0 0 0 100vmax rgba(52,18,31,.42);
  }
  .cp-panel:has(.cp-search[hidden]){
    top:auto;bottom:0;border-bottom:0;border-top:1px solid var(--oxblood);
    padding:10px 0 calc(10px + env(safe-area-inset-bottom,0px));
  }
  .cp-list{max-height:min(52dvh,380px)}
  .cp-list li{min-height:48px;padding:0 var(--gutter);font-size:15px}   /* was 39px, x53 rows */
  .cp-list li[aria-selected="true"]{box-shadow:inset 3px 0 0 var(--tomato)}
  .cp-none{padding:14px var(--gutter);font-size:14px}
  /* A scroll drag on a 48px row should read as a scroll, not a press. */
  .cp-list{touch-action:pan-y}
  .cp-list li{-webkit-user-select:none;user-select:none}

  /* THE SHEET ONLY WORKS IF NOTHING ABOVE IT IS A CONTAINING BLOCK, and
     something is. .board-intro carries animation:rise ... both
     (style.css:271-274), whose keyframes animate transform — and Chrome
     treats an element with a transform animation as will-change:transform
     for as long as the animation exists, filled or not, so .board-intro
     is permanently a containing block for fixed descendants. I measured
     it: the "fixed" panel opens at x=18 y=1710 inside the board column
     instead of at 0,0. Swapping the board intro's reveal for an
     opacity-only one on the phone removes the transform, and with it the
     containing block, while keeping the reveal. Measured after: 0,0,
     full width. The composer's two pickers are unaffected — nothing on
     that path animates. */
  .board-intro{animation-name:fade}

  /* The page must not scroll the trigger away from under a sheet that
     cannot follow it. overscroll-behavior:contain already covers drags
     inside the list; this covers the rest of the sheet. */
  html:has(.cp-panel:not([hidden])){overflow:hidden}

  /* .cp-trigger alone loses to .composer .cp-trigger (style.css:354) at
     (0,2,0) regardless of source order, which would leave the board's
     trigger at 16px/54px and the composer's two at 15px/50px — two sizes
     of the same control. 16px is also the iOS zoom floor for the search
     field below. */
  .cp-trigger,
  .composer .cp-trigger{font-size:16px;padding:14px}
  /* One control, one build: .cp-search is caught by .composer-form
     input[type=text] (:242) and would otherwise come out 15px in the
     composer against 13px on the board. The second selector is what
     out-ranks that, at (0,2,1). */
  .cp-search,
  .composer-form input.cp-search{
    width:calc(100% - var(--gutter) * 2);margin:0 var(--gutter) 8px;
    min-height:48px;padding:11px 12px;font-size:16px;
  }

  /* THE COMPOSER BECOMES A SHEET, because on a touchscreen it currently
     has no exit. .composer-dismiss is position:absolute (style.css:233)
     inside the box the UA gives overflow:auto, so it scrolls with the
     content and is gone by the time you reach the submit button; there
     is no backdrop-close handler (script.js:460-473), no closedby, and
     no Escape key on a phone. Two grid rows fix it structurally: row 1
     never scrolls, only row 2 does.
     [open] IS THE WHOLE RULE. The UA hides a closed dialog with
     dialog:not([open]){display:none}, and an author display:grid beats a
     UA declaration at any specificity — on .composer it would render the
     composer over the entire page, at inset:0, on every phone, and the
     landing page would never be seen. Scope every layout declaration to
     the open state; the descendants below are already inert when the
     dialog is hidden.
     dvh is what makes the sheet the size of what is on screen — 100% on
     a fixed element resolves against the LARGE viewport on iOS, which is
     how the submit button ends up behind the toolbar — and the 100vh
     pair is not redundant: max-height:100dvh alone is dropped wholesale
     by a browser without dvh, handing the dialog back to the UA's
     max-height:calc(100% - 6px - 2em) and cutting 38px off a 100vh
     sheet.
     Deliberately no entrance animation: a transform on the dialog would
     make it a containing block and swallow the fixed picker sheet above.
     overflow:hidden here does not clip that sheet — an ancestor only
     clips a fixed descendant if it is its containing block. */
  .composer[open]{
    width:100%;max-width:none;margin:0;inset:0;
    height:100vh;height:100dvh;max-height:100vh;max-height:100dvh;
    display:grid;grid-template-rows:auto minmax(0,1fr);
    overflow:hidden;
  }
  .composer::backdrop{background:rgba(52,18,31,.55)}
  .composer-dismiss{
    position:static;display:flex;justify-content:flex-end;
    padding:max(4px,env(safe-area-inset-top,0px)) 6px 4px;
    border-bottom:1px solid var(--rule-faint);
  }
  .composer-dismiss button{
    width:48px;height:48px;                 /* was 26.6 x 24 */
    display:flex;align-items:center;justify-content:center;
    font-size:26px;color:var(--oxblood);
  }
  .composer-inner{
    min-height:0;overflow-y:auto;overscroll-behavior:contain;
    padding:20px var(--gutter) 0;
    /* the UA scrolls a focused field to the scrollport edge; tell it
       where the usable edge is, or tabbing into #email-input, the
       consent box or either picker trigger parks them under the sticky
       submit button (SC 2.4.11) */
    scroll-padding-bottom:calc(88px + env(safe-area-inset-bottom,0px));
  }

  /* Order-only flex so the primary action can be sticky and the status
     message still sit above it. Nothing is lost to margin collapsing:
     every rule in .composer-form already zeroes one facing margin of
     each adjacent pair.
     The [hidden] guard is the same trap as #use-location and .cp-panel,
     and here it is the product's only conversion event: script.js:375
     sets #post-form.hidden = true and :376 unhides #success, and
     <form class="composer-form" id="post-form"> is that element. Without
     the guard the success panel renders with the entire form still under
     it and a live sticky "Put it up" pinned to the bottom of the sheet. */
  .composer-form{display:flex;flex-direction:column}
  .composer-form[hidden]{display:none}
  #post-message{order:98;margin:12px 0 0}
  .composer-form .btn{
    order:99;position:sticky;bottom:0;z-index:3;
    margin:24px calc(var(--gutter) * -1) 0;
    width:calc(100% + var(--gutter) * 2);
    min-height:56px;
    padding:18px max(15px,env(safe-area-inset-right,0px))
            calc(18px + env(safe-area-inset-bottom,0px))
            max(15px,env(safe-area-inset-left,0px));
    box-shadow:0 -1px 0 var(--rule-faint);
  }
  /* The global focus style is outline:2px with offset:3px (style.css:38),
     drawn 3px OUTSIDE a box that now runs edge to edge — left, right and
     bottom land outside the viewport and html{overflow-x:clip} eats them
     silently. Inside, in paper: 3.852:1 on the tomato it sits on, which
     clears 1.4.11's 3:1 without leaving the box. */
  .composer-form .btn:focus-visible{outline:2px solid var(--paper);outline-offset:-5px}

  /* No focusable text field under 16px, or iOS Safari zooms the viewport
     on focus and leaves it there. Today: #when-input 13.3px (see 9.0),
     #email-input 15px via font:inherit, .cp-search 13px. The textarea is
     deliberately NOT in this selector — style.css:247 already sets it to
     17px, and sweeping it in here would make the one field the whole
     dialog exists for smaller on a phone than on a desktop. */
  .composer-form input:not([type=checkbox]):not([type=radio]):not([type=hidden]){font-size:16px}

  /* A 13 x 13px checkbox carrying two links a near-miss would toggle
     instead of open. The links get pseudo-element targets rather than
     padding: .consent a carries border-bottom:1px solid var(--tomato)
     (style.css:261), and padding an inline-block pushes that rule to the
     bottom of the padding box — two loose red dashes floating 10px under
     the words, in a design whose whole vocabulary is a fine rule under a
     word. The two links are separated by " · ", so -3px gives each a
     44px target without the two overlapping. */
  .consent{min-height:44px;gap:12px}
  .consent input{width:24px;height:24px;margin:1px 0 0;accent-color:var(--tomato)}
  .consent a{position:relative;display:inline;padding:0;margin:0}
  .consent a::after{
    content:'';position:absolute;left:-3px;right:-3px;
    top:50%;height:44px;transform:translateY(-50%);
  }

  /* THE COLOPHON AS A BACK-PAGE INDEX. The five links are 18px tall and
     20px apart, so 44px targets would overlap each other. Two ruled
     columns is how a magazine sets a back-page index: it is the board's
     own column-and-hairline vocabulary, and it is three rows rather than
     five. Contact takes the full measure on row three, because a
     hairline that stops dead at the column gutter with an empty cell
     beside it is the one thing a reader will read as a bug.
     "One line. Two weeks." deliberately stays in Inter: setting it in
     Anton would be a closing display statement the desktop page does not
     have, and mobile must feel like the same publication, not a better
     one. Supersedes :219, :222, :296-298. */
  .colophon{
    text-align:left;gap:0;
    padding:28px var(--gutter) calc(28px + env(safe-area-inset-bottom,0px));
  }
  .colophon-tag{margin:0 0 20px}
  .colophon nav{
    display:grid;grid-template-columns:1fr 1fr;gap:0;
    border-top:1px solid var(--rule-faint);margin:0 0 20px;
  }
  .colophon nav a{
    display:flex;align-items:center;min-height:48px;    /* was 18px */
    font-size:13px;border-bottom:1px solid var(--rule-faint);
  }
  .colophon nav a:nth-child(odd){padding-right:14px}
  .colophon nav a:nth-child(even){padding-left:14px;box-shadow:inset 1px 0 0 var(--rule-faint)}
  .colophon nav a:last-child{grid-column:1/-1;padding-right:0}
  .colophon-meta{text-align:left;margin:0;max-width:34ch}
}


@keyframes fade{from{opacity:0}to{opacity:1}}


/* ── 9.4 Touch ────────────────────────────────────────────────────────
   On iOS a tap latches :hover until the next tap elsewhere, so tapping a
   board banner leaves it permanently scaled and the CTA permanently in
   its pressed #B93B26 — the page looks stuck. Nine unguarded :hover
   rules (style.css:71, 81, 83, 93, 184, 221, 329, 363, 401), neutralised
   only where there is no pointer to hover with.
   The :not() on the trigger is deliberate: .cp-trigger[aria-expanded]
   shares the same (0,2,0) as .cp-trigger:hover and would otherwise lose
   its open state to this block on source order. */
@media(hover:none){
  .masthead-nav a:hover::after{transform:scaleX(0)}
  .btn-accent:hover{background:var(--tomato)}
  .btn-dark:hover{background:var(--oxblood)}
  .quiet-link:hover{color:var(--ink-soft)}
  .line-photo:hover img{transform:none}
  .colophon nav a:hover{color:var(--ink-soft)}
  .cp-trigger:not([aria-expanded="true"]):hover{border-color:var(--rule)}
  .lang-switch a:hover{color:inherit;border-bottom-color:transparent}
}

/* ── 10. The two gender controls ───────────────────────────────────────
   "Who can answer" used to be one dropdown mixing four axes — gender,
   orientation, age and tenure — so a straight man could not say "women"
   without broadcasting to everyone. It is now one axis and more than one
   answer, which a <select> cannot express at all.

   Real radios and checkboxes, not divs with roles: keyboard, screen
   reader, form serialisation and the browser's own grouping come free,
   and a <fieldset>/<legend> is the only markup that reads the group's
   name before each option rather than after. The input is hidden from
   sight but never from the accessibility tree or from focus — it is
   opacity, not display:none — and the chip carries the focus ring on its
   behalf through :has().

   Square corners and a hairline, like every other control on the page. */
.chipset{border:0;margin:18px 0 0;padding:0;min-width:0}
.chipset legend{
  padding:0;margin:0 0 9px;
  font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.15em;
}
.chips{display:flex;flex-wrap:wrap;gap:8px}

/* Scoped to .composer-form, at (0,2,0), because a .chip IS a <label> and
   style.css:238 styles every label in this form as a 10px uppercase caption
   with an 18px top margin — which made the chips 10px tracked caps, and
   staggered them down the page instead of laying them in a row. */
.composer-form .chip,
.chip{
  position:relative;display:inline-flex;
  margin:0;padding:0;
  font-size:inherit;font-weight:400;text-transform:none;letter-spacing:normal;
}
.chip input{
  position:absolute;inset:0;width:100%;height:100%;
  margin:0;opacity:0;cursor:pointer;
}
.chip span{
  display:flex;align-items:center;min-height:44px;padding:0 15px;
  letter-spacing:normal;text-transform:none;
  border:1px solid var(--rule);background:#F7F4EA;color:var(--oxblood);
  font-size:14px;line-height:1.2;
  transition:background var(--t-control) var(--ease),
             border-color var(--t-control) var(--ease),
             color var(--t-control) var(--ease);
}
.chip:hover span{border-color:var(--oxblood)}
.chip input:checked + span{
  background:var(--oxblood);border-color:var(--oxblood);color:var(--paper);
}
/* The ring goes on the chip, because the input it belongs to is invisible.
   :focus-visible and not :focus — a mouse click on a label focuses the
   input, and a ring on every click reads as a bug. */
.chip:has(input:focus-visible) span{outline:2px solid var(--tomato);outline-offset:3px}

/* The live consequence, in the sentence the person just wrote. Never a
   warning: naming an audience is a legitimate choice, and the note says
   what it does rather than talking them out of it. */
#audience-note{margin:10px 0 0;border-left:2px solid var(--tomato);padding-left:10px}

@media(hover:none){ .chip:hover span{border-color:var(--rule)} }
@media(max-width:620px){
  .chip span{min-height:48px;font-size:15px;padding:0 14px}
  .chips{gap:7px}
}


/* ── 11. Two corrections ───────────────────────────────────────────────
   (a) The board's city trigger and "Use my location" were collapsed into
   one ruled control by a -1px margin. Read back, they are too tight: the
   trigger is a dropdown and the button is an action, and one shared rule
   says they are two rows of the same list. Give the action its own air
   and its own rule, and drop the border on three sides so it still reads
   as part of the control group rather than as a second field. */
@media(max-width:900px){
  #use-location{
    margin:10px 0 0;
    border:0;background:transparent;
    padding:0;min-height:44px;
  }
}


/* ── 12. The board page ────────────────────────────────────────────────
   /board/ is the page the masthead has been promising since the site went
   up: "The board" pointed at #board, a section on the landing page that
   showed two hard-coded examples and, the moment a real line existed,
   replaced them with two rows of text and no photograph. The board's best
   state was the fake one.

   So the landing page keeps the photographs and the two examples, clearly
   labelled, and this page is the board: every standing line, typographic,
   no art. The photographs on the landing page are editorial — they are of
   places, and they are illustrating an idea. A real line is somebody's
   sentence, and putting a stock photograph over it would be the lie the
   rest of this product is built to avoid. */
.ledger-head{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,26rem);
  gap:0 var(--gutter);align-items:end;
  padding:54px var(--gutter) 34px;
  border-bottom:1px solid var(--rule);
}
.ledger-title .display{font-size:clamp(44px,7.4vw,110px);line-height:.93;margin:0 0 18px}
.ledger-body{max-width:34ch;font-size:15px;line-height:1.5;color:var(--ink-soft);margin:0}
.ledger-controls{display:flex;flex-direction:column;gap:12px;padding-bottom:4px}
.ledger-count{
  margin:0;font-size:10px;font-weight:600;letter-spacing:.17em;
  text-transform:uppercase;color:var(--ink-soft);
}

.ledger{padding:0 0 10px}
.ledger-loading,.ledger-empty{
  margin:0;padding:44px var(--gutter);font-size:15px;line-height:1.5;color:var(--ink-soft);
  max-width:46ch;
}

/* One entry, one ruled row. The rule belongs to the row it introduces, so
   the first entry carries none — the section's own border above it is that
   line, and two rules 1px apart read as a mistake. */
.entry{padding:26px var(--gutter)}
.entry + .entry{border-top:1px solid var(--rule-faint)}
.entry-meta{
  display:flex;justify-content:space-between;gap:16px;margin:0 0 10px;
  font-size:10px;font-weight:600;letter-spacing:.17em;text-transform:uppercase;
}
.entry-city{color:var(--oxblood)}
.entry-left{color:var(--ink-soft)}
.entry-body{
  margin:0;max-width:26ch;
  font-size:clamp(20px,2.4vw,30px);line-height:1.22;letter-spacing:-.012em;
}
.entry-when,.entry-who{margin:9px 0 0;font-size:13px;line-height:1.45;color:var(--ink-soft)}
/* Who is asking and who it is addressed to — the two halves a printed
   personals column set in italic, for the same reason: it is the frame
   around the sentence, not part of it. */
.entry-who{font-style:italic}
.entry .answer{margin-top:14px}
/* The landing page's two-line preview carries the same half. */
.line-who{margin:8px 0 0;font-size:13px;font-style:italic;color:var(--ink-soft)}

.ledger-cta{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:18px var(--gutter);
  padding:34px var(--gutter) 44px;border-top:1px solid var(--rule);
}
.ledger-cta-copy{margin:0;max-width:40ch;font-size:15px;line-height:1.5}

@media(max-width:900px){
  .ledger-head{grid-template-columns:1fr;gap:28px;padding:34px var(--gutter) 26px}
  .ledger-controls{padding-bottom:0}
  .entry-body{font-size:clamp(20px,calc(6.2vw - 2.2px),30px);max-width:none}
}


/* ── 13. The display type has to fit in three languages ────────────────
   The mobile headline is sized so that its widest hard-broken line fills
   the measure, and that line is a different word in every locale. Solved
   for the English "another" alone, Spanish overran by 1.2% at EVERY width
   — "Quédate" is 3.0118em against another's 2.8797em — and
   html{overflow-x:clip} (style.css:26) would have swallowed the evidence
   rather than showing a scrollbar. The English board page overran by
   10.7px for the same reason: "Everything" is 3.8755em, and .ledger-title
   is a grid child whose min-content simply pushed the track wider.

   So the coefficient is a token, and there is one per locale, each
   measured off the shipped anton.woff2 at the letter-spacing this build
   actually sets rather than estimated from character counts. Target fill
   is 96.7% — the English hero's own value — which leaves ~3% of clear
   paper so that no locale is one rounding error from clipping.

       hero    en "another"    2.8797em      fr "pour un"    2.8318em
               es "Quédate"    3.0118em
       board   en "Everything" 3.8755em      fr "en ce moment." 3.2890em
               es "está publicado" 3.6487em

   font-size = k x measure, and below 620.7px the measure is exactly
   100vw - 36px because --gutter is pinned at 18px there. Written as
   calc(k * (100vw - 36px)) rather than the equivalent "33.6vw - 12.1px"
   so the two numbers that matter are both visible and neither has to be
   re-derived by hand when a headline changes. */
/*     k = .967 / (widest line, in em)          measured on the live pages
       hero    en "another"     2.8790em      fr "de plus."    2.8925em
               es "Quédate"     3.0107em
       board   en "Everything"  3.8746em      fr "affiché."    2.7204em
               es "publicado."  3.8410em                                    */
:root{--h1-fit:.3359;--ledger-fit:.2496}
html[lang="fr"]{--h1-fit:.3343;--ledger-fit:.3555}
html[lang="es"]{--h1-fit:.3212;--ledger-fit:.2518}

@media(max-width:900px){
  .hero-copy .display{font-size:min(calc(var(--h1-fit) * (100vw - 36px)),134px)}
  .ledger-title .display{font-size:min(calc(var(--ledger-fit) * (100vw - 36px)),134px)}
}

/* Desktop has the same problem in the other direction: .ledger-title is a
   grid child, so a long unbreakable display word grows the track instead
   of wrapping. minmax(0,1fr) lets it shrink; the word can then only be
   capped, never overflow. */
.ledger-title{min-width:0}
.ledger-title .display{overflow-wrap:break-word}
