/* landing.css — bind.com "/" THE SPLIT LANDING (R319/§312 SESSION-BIND, piece landing-split; BRIEF 1, 13, 23-28, 30, 31).

   NOT ONE COLOUR IS DECLARED HERE. Every paint in this file is a semantic custom property out of tokens.css —
   --w-* for the WALL half (the MERIDIAN dawn) and --d-* for the LEGACY DOOR (the hallway) — so the two halves
   carry two distinct ladder palettes and neither one can drift off the goldenratiocolors ladder from this file.
   tests/split-gate.mjs refuses any literal colour in these three files, which is why the rule is worth stating.

   THE SPLIT READS IN ONE SECOND because three things say it at once:
     the ground      cool pale sky (#c3f1ff light / #0e2525 dark) against warm parchment (#dadac3 / #3c3c25),
                     a hue difference before it is a luminance difference — the way the Acne bar's two portals
                     read as two portals before you have read a word;
     the rule        one hairline where they meet, carried by the LEGACY half's own border so it can never be
                     drawn twice or land a pixel off the boundary;
     the wordmark    "bind" set across that rule at 13vw, one word in two inks — the half over the wall in
                     --w-ink, the half over the door in --d-ink, clipped exactly on the seam.

   LAW 1 — no plain viewport-height unit anywhere: dvh for a whole screen, and svh wherever the number has
           to be honest about the screen you can actually see — the stacked wall half's cap, and the short viewport.
   LAW 2 — the ONLY width switch is @container page (the split itself, and the stacked wall half's cap) and
           @container halfbody (the door grid).
           The viewport media queries in this file are the page shell's own and nothing else: prefers-color-scheme
           is not used (tokens.css owns the scheme), prefers-reduced-motion, forced-colors, hover/pointer, and one
           height query — the (max-height: 480px) that turns each half's dvh into svh, which is the page-shell
           geometry ASL Law 4 and this piece's own spec ask for by name.
   LAW 5 — every door row, and the sale link, clears 44 px by min-block-size, not by padding luck; focus is a
           3 px ring in the half's own --*-focus token, on every focusable element, in both families.
   LAW 6 — motion is a hard stop, not a shorter show: every animation and every transition in this file lives
           inside @media (prefers-reduced-motion: no-preference), so under reduce the rules do not exist and
           document.getAnimations() is empty. There is one animation on the page and it plays once.
   LAW 7 — the two-ink wordmark is a clip-path enhancement inside @supports; where clip-path is unknown the
           second copy is not painted at all and the word is one ink, still over 8:1 on both grounds. */

/* ============================================================================================================
   0. RESET AND PAGE GROUND
   ========================================================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
html { background: var(--w-paper); -webkit-text-size-adjust: 100%; }
body {
  /* THE PAGE-SHELL CONTAINER LIVES HERE, NOT ON .page, and the reason is a rule of the feature rather than a
     preference: an element can never query its own container, so a `container:` on .page would have left
     `@container page { .page { ... } }` — the split switch itself — permanently unmatched while every rule on a
     DESCENDANT matched, which is exactly the half-applied layout the first render showed (the seam took its
     side-by-side position while the columns stayed stacked, 191 px of horizontal overflow). The query container
     is therefore one level above the element it switches. */
  container: page / inline-size;
  background: var(--w-paper);
  color: var(--w-ink);
  font-family: var(--font-body);
  font-size: var(--fs-0);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
}
[hidden] { display: none !important; }

/* the icon idiom of the estate: inline SVG from icons.js, em-sized, currentColor, never an emoji */
.ic { inline-size: 1em; block-size: 1em; flex: none; vertical-align: -0.14em; }

/* ============================================================================================================
   1. THE PAGE SHELL — the split
   ========================================================================================================== */
.page {
  display: grid;
  grid-template-columns: minmax(0, 1fr);

  /* HOW TALL A HALF IS — and the one number on this page that is deliberately not a whole screen.
     --half-b IS a whole first screen, and that is what a half is: the legacy door keeps it in both layouts and
     the wall half keeps it side by side. --wall-b is the STACKED wall half, and it stops short on purpose.
     Below the 64rem switch a wall half of a whole screen puts the seam exactly ON the fold — measured on the
     r2 build at 390x844 the legacy ground began at y=844 with 20.2px of the 48px wordmark showing above it,
     and at 844x390 the seam sat at y=530.4 with the whole wordmark 117px BELOW the fold. A split page whose
     split is not on the first screen is not a split page. 82svh brings the rule, a band of the door's warm
     ground and the whole two-ink wordmark inside the fold, which is what the bar does with the same geometry:
     Acne Studios at 390x844 ends SHOP WOMAN and begins SHOP MAN at y=633, 75% of its own fold
     (reference/SPLIT-acnestudios/acnestudios__390x844__fold.png). svh and not dvh, because a cap has to be
     honest about the screen that is actually there — a dvh cap would hide the band again the moment a
     browser bar came back. */
  --half-b: 100dvh;
  --wall-b: 82svh;

  /* the wordmark's own metrics, needed by both the seam and the clearance the halves keep for it */
  --wm: clamp(3.75rem, 13vw, 13rem);
  --wm-box: calc(var(--wm) * 0.8);
  --seam-drop: clamp(2rem, 7dvh, 5rem);

  --pad-i: clamp(var(--s2), 4vw, var(--s5));
  --pad-b: clamp(var(--s3), 3dvh, var(--s4));
}

.half {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s3);
  min-block-size: var(--half-b);
  padding-inline: max(var(--pad-i), var(--sal)) max(var(--pad-i), var(--sar));
  padding-block: max(var(--pad-b), var(--sat)) max(var(--pad-b), var(--sab));
}

/* THE STACKED WALL HALF STOPS SHORT OF THE SCREEN, AND THE DOORS ARE WHERE THE BLOCK AXIS IS FOUND.
   Capped at --wall-b the wall half is a screen minus the band that shows the door underneath it, so the rule,
   that band and the whole wordmark are ON the first screen instead of under it. The seven doors are the one
   part of the half that may not shrink to pay for it — ASL Law 5 pins every row at --target and the day's
   tile at 1.7x it — so where the cap is tighter than the list, the list is what gives: .half__body becomes the
   internal scroll region ASL Law 4 names by name, with a thin scrollbar in the wall's own rule colour so the
   scroll is a visible affordance rather than a trap, and with scroll chaining left ON so a swipe that runs
   out of doors carries on down the page to the legacy half.
   THE MAXIMUM IS THE HALF THAT DOES THE WORK, and this round found that out by measuring rather than by
   reasoning. The minimum alone looked sufficient — the body carries min-block-size: 0, so its 1fr track is
   free to shrink under its own content — and it is not: with only a minimum the container's block size is
   indefinite, an fr track in an indefinite container sizes to its items' content, and the half went straight
   back to 761.9px at 390x844 and 486.1px at 844x390 with the seam under the fold again (both measured, this
   round, on this file). The maximum is what makes the size definite and the free space distributable, which
   is what the scroll region needs. min and max carry the same value on purpose: a stacked wall half is 82%
   of the screen at every profile, not 82% only where its content happens to reach that far.
   WHAT THE MAXIMUM COSTS is that the rows which cannot scroll — the eyebrow, the foot and the shell's own
   block padding — must fit inside the cap or they would spill over the legacy half instead of scrolling.
   They come to 143.8px of a 319.8px cap on the shortest profile the matrix runs (844x390), a 176px margin,
   and the gate below measures the whole half at every stacked profile so a future row that ate that margin
   would be named rather than discovered.
   THE PLACEMENT IS LOAD-BEARING, for the same reason section 3b's is. `.half--wall` and `.half` are both
   single-class selectors, so this block beats `.half { min-block-size: var(--half-b) }` only by standing
   AFTER it — and nothing later in this file may set a block-size on either selector again. That is why the
   short-viewport block now sets --half-b on .page instead of min-block-size on .half: a custom property
   nothing else declares cannot lose a source-order fight. */
@container page (width < 64rem) {
  .half--wall { min-block-size: var(--wall-b); max-block-size: var(--wall-b); }
  .half--wall .half__body { overflow-block: auto; scrollbar-width: thin; scrollbar-color: var(--w-rule) transparent; }
}

/* ASL Law 4 — the short viewport (landscape phone, keyboard open) is the one height query in this file, and it
   is NOT written here. It sets .head and .lede, and a rule of the same specificity only wins when it comes
   LATER, so the whole block lives at the end of section 3, after the type it steps down.
   See "3b. THE SHORT VIEWPORT" below — that placement is load-bearing, not filing. */

.half--wall   { background: var(--w-paper); color: var(--w-ink); z-index: 1; }
.half--legacy { background: var(--d-paper); color: var(--d-ink); border-block-start: 1px solid var(--d-rule); }

.half__body {
  /* stretch, not centre: the body has to FILL its track for the cap above to have anything to clamp — an
     align-self: center item sizes to its own content and spills out of the half instead of scrolling inside
     it. min-block-size: 0 drops the automatic minimum a grid item otherwise carries, which is the other half
     of the same requirement. `safe center` keeps the content optically centred while it fits and falls back
     to start alignment the moment it does not, so the headline can never be scrolled off the TOP of its own
     scroll region — the failure a plain `center` makes on every box that overflows. */
  align-self: stretch;
  min-block-size: 0;
  display: grid;
  gap: var(--s2);
  align-content: safe center;
  container: halfbody / inline-size;
}

/* THE SPLIT ITSELF. 64rem is 1024 px at the default root size — the width the spec names — and it is a rem so
   that at 200% zoom (a 1440 laptop laying out at 720 CSS px) the page stacks, which is what a reflowed page owes
   a reader. Two equal columns; side by side neither half is capped, so each one is --half-b (a whole screen)
   tall and the fold holds both halves whole - the cap above is a rule of the STACKED layout only. */
@container page (min-width: 64rem) {
  .page { grid-template-columns: 1fr 1fr; }
  .half--legacy { border-block-start: 0; border-inline-start: 1px solid var(--d-rule); }
}

/* ============================================================================================================
   2. THE SEAM — the rule, and the wordmark set across it
   ========================================================================================================== */
/* Anchored to the wall half's own end edge, which IS the boundary in both layouts (an absolutely positioned box
   is laid out against its ancestor's padding box, and the half carries no border on the seam side), then pulled
   out by half of itself so its centre line sits exactly on the rule. Nothing here is interactive and nothing
   here can be clicked through to. */
.seam {
  position: absolute;
  inset-inline: 0;
  inset-block: auto 0;
  translate: 0 50%;
  display: grid;
  justify-items: center;
  pointer-events: none;
  z-index: 2;
}

.seam__word {
  display: grid;
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--wm);
  line-height: 0.8;
  letter-spacing: var(--ls-display);
  white-space: nowrap;
}
/* both copies occupy the one grid cell, so they are the same box to the pixel */
.seam__ink { grid-area: 1 / 1; color: var(--w-ink); }

/* the door's half of the word. Not painted at all where clip-path is unknown (ASL Law 7): the word is then one
   ink, and --w-ink still clears 8.27:1 on the light door ground and 9.65:1 on the dark one. */
.seam__ink--door { display: none; color: var(--d-ink); }
@supports (clip-path: inset(50% 0 0 0)) {
  .seam__ink--door { display: block; clip-path: inset(50% 0 0 0); }
}

@container page (min-width: 64rem) {
  .seam { inset-inline: auto 0; inset-block: auto var(--seam-drop); translate: 50% 0; }
  @supports (clip-path: inset(0 0 0 50%)) {
    .seam__ink--door { clip-path: inset(0 0 0 50%); }
  }
}

/* the clearance each half keeps so the word never lands on live text: half the word's box on the stacked seam,
   the whole box plus its drop on the side-by-side one. */
.half--wall   { padding-block-end:   calc(max(var(--pad-b), var(--sab)) + var(--wm-box) * 0.62); }
.half--legacy { padding-block-start: calc(max(var(--pad-b), var(--sat)) + var(--wm-box) * 0.62); }
@container page (min-width: 64rem) {
  .half--legacy { padding-block-start: max(var(--pad-b), var(--sat)); }
  .half { padding-block-end: calc(max(var(--pad-b), var(--sab)) + var(--seam-drop) + var(--wm-box)); }
}

/* ============================================================================================================
   3. SHARED TYPE — the eyebrow, the head, the lede, the foot
   ========================================================================================================== */
.eyebrow {
  display: flex; align-items: center; gap: var(--s1);
  margin: 0;
  font-family: var(--font-mono); font-size: var(--fs--1); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  color: var(--w-ink2);
}
.half--legacy .eyebrow { color: var(--d-ink2); }

.head {
  margin: 0;
  font-family: var(--font-display); font-weight: var(--fw-display);
  font-size: var(--fs-4); line-height: var(--lh-tight); letter-spacing: var(--ls-display);
  text-wrap: balance;
}
.head--sale {
  font-family: var(--font-narrow); font-weight: var(--fw-bold);
  line-height: var(--lh-snug); letter-spacing: -0.012em;
}

.lede { margin: 0; font-size: var(--fs-1); color: var(--w-ink2); max-inline-size: var(--measure); }
.lede--sale { color: var(--d-ink2); max-inline-size: var(--measure-wide); }

.foot {
  align-self: end; margin: 0;
  font-family: var(--font-mono); font-size: var(--fs--1); line-height: var(--lh-body);
  letter-spacing: 0.04em; color: var(--w-ink2); max-inline-size: var(--measure-wide);
}
.half--legacy .foot { color: var(--d-ink2); }
.foot__code { color: var(--w-ink); }
.foot__warn { display: block; color: var(--w-deny); }

/* ============================================================================================================
   3b. THE SHORT VIEWPORT — ASL Law 4, the page shell's own geometry, and the only height query in this file
   ========================================================================================================== */
/* WHY THE BLOCK IS DOWN HERE AND NOT UP WITH .half. It was written in section 1, next to the min-block-size it
   changed, and for the first round it was WRONG THERE and the file said so anyway. `.head` and `.lede` are
   single-class selectors, and so are the base rules thirty lines above this comment; equal specificity is
   decided by source order, so the base font sizes — declared LATER — simply won. Measured on the r1 build at
   844x390: .head computed 54.2px, which is --fs-4 at that width, not the 22px this block asks for. The prose
   promised a step-down the cascade never delivered, which is exactly the kind of claim a gate is for, and the
   stack arm of tests/split-gate.mjs now measures both live sizes at both short profiles and plants the defect
   back to prove the measurement bites.
   THE SAME TRAP IS NOW DISARMED RATHER THAN DODGED. This block no longer sets a block-size on .half at all:
   it sets --half-b on .page and .half reads it, so the cap in section 1 stays the last word on how tall a
   half is no matter where this block stands. Only .head and .lede still depend on the placement.
   dvh on a short viewport is the tall reading of a screen that is about to grow a browser bar back; svh is the
   honest one, so a half is one screen you can actually see. The wordmark and the headline are the two things
   that make a half into two screens, so both step down — and the shell's own block padding and gaps come down
   in the same step, because on a 390px-tall screen every one of those millimetres is a millimetre of the day's
   door that is on the first screen instead of under it. The doors themselves do NOT shrink: they are the
   targets, ASL Law 5 outranks fitting the fold, and the list scrolls instead. */
@media (max-height: 480px) {
  .page { --half-b: 100svh; --wm: clamp(3rem, 8vw, 5rem); --seam-drop: var(--s3); --pad-b: var(--s2); }
  .half { gap: var(--s1); }
  .half__body { gap: var(--s1); }
  .head { font-size: var(--fs-2); }
  .lede { font-size: var(--fs-0); }
}

/* ============================================================================================================
   4. THE SEVEN DOORS
   ========================================================================================================== */
.doors { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s0); }

/* the head of the list is the day's door: landing.js moves it there, so first in the DOM, first on the screen
   and first in the tab ring are one element. Without script the head is door 1 and the page is still complete. */
.doors > li:first-child { grid-column: 1 / -1; }

@container halfbody (min-width: 34rem) {
  .doors { grid-template-columns: 1fr 1fr; column-gap: var(--s2); }
}

.door {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--s2);
  min-block-size: var(--target);
  padding: var(--s0) var(--s1);
  border-block-end: 1px solid var(--w-edge);
  color: var(--w-ink);
  text-decoration: none;
}
.door__n {
  font-family: var(--font-display); font-weight: var(--fw-display); font-size: var(--fs-1);
  line-height: var(--lh-tight); font-variant-numeric: lining-nums tabular-nums;
  color: var(--w-ink2);
}
.door__title { font-size: var(--fs--1); line-height: var(--lh-snug); overflow-wrap: anywhere; }
.door__state { display: none; }

/* the day's door: the largest thing on the wall, and the only row that wears the pulse */
/* THE DAY'S DOOR — the largest thing on the wall, and the only row that wears the pulse. Two rows rather than
   a third column: a third column made the state word compete with the title for the same inline space, and at
   390 px the title lost (it wrapped to three lines while "OPEN TODAY" kept its own). Stacking the state under
   the title gives the title the whole width at every size, and the numeral spans both rows as the tile's spine. */
.doors > li:first-child .door {
  min-block-size: calc(var(--target) * 1.7);
  padding: var(--s2);
  background: var(--w-raised);
  border: 1px solid var(--w-rule);
  border-inline-start: var(--s0) solid var(--w-accent);
  border-radius: var(--r1);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: var(--s3);
  row-gap: var(--s0);
}
.doors > li:first-child .door__n { grid-row: 1 / 3; font-size: var(--fs-3); color: var(--w-ink); }
.doors > li:first-child .door__title { grid-column: 2; font-size: var(--fs-1); font-weight: var(--fw-medium); }
.doors > li:first-child .door__state {
  grid-column: 2;
  display: flex; align-items: center; gap: 0.6em;
  font-family: var(--font-mono); font-size: var(--fs--1); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-key); text-transform: uppercase; color: var(--w-ink2);
}
.door__go { font-size: 1.35em; }

/* ============================================================================================================
   5. THE SALE LINK — the legacy door's one action
   ========================================================================================================== */
.sale {
  display: block;
  min-block-size: var(--target);
  color: var(--d-ink);
  text-decoration-line: underline;
  text-decoration-color: var(--d-rule);
  text-decoration-thickness: 0.05em;
  text-underline-offset: 0.16em;
}

/* ============================================================================================================
   6. FOCUS — visible everywhere, in the half's own family (ASL Law 5)
   ========================================================================================================== */
.half--wall a:focus-visible   { outline: 3px solid var(--w-focus); outline-offset: 3px; border-radius: var(--r1); }
.half--legacy a:focus-visible { outline: 3px solid var(--d-focus); outline-offset: 3px; border-radius: var(--r1); }

/* ============================================================================================================
   7. MOTION — one animation, once, and only where motion is welcome (ASL Law 6)
   ========================================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .seam__word { animation: wm-arrive var(--dur-slow) var(--ease) 1; }
  @keyframes wm-arrive { from { opacity: 0; translate: 0 0.22em; } }

  .door { transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
  .sale { transition: text-decoration-color var(--dur-fast) var(--ease); }
}
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .door:hover { background: var(--w-raised); border-color: var(--w-rule); }
  .sale:hover { text-decoration-color: var(--d-ink); }
  #bindNotices .bind-note__x:hover { color: var(--w-ink); border-color: var(--w-edge); }
}
/* a coarse pointer never hovers, so the same affordance is offered to the finger by :active (ASL Law 5:
   nothing reachable only via :hover when hover is none) */
.door:active { background: var(--w-raised); }
.sale:active { text-decoration-color: var(--d-ink); }
#bindNotices .bind-note__x:active { color: var(--w-ink); border-color: var(--w-edge); }

/* ============================================================================================================
   8. FORCED COLOURS — the OS owns the palette; only the split's own identity is ours to keep
   ========================================================================================================== */
@media (forced-colors: active) {
  /* the two grounds collapse to one Canvas, so the seam has to carry the split on its own: the rule thickens
     and the day's door keeps an outline instead of a fill it is no longer allowed to paint. */
  .half--legacy { border-block-start-width: 3px; }
  @container page (min-width: 64rem) {
    .half--legacy { border-block-start-width: 0; border-inline-start-width: 3px; }
  }
  .doors > li:first-child .door { outline: 2px solid CanvasText; outline-offset: -4px; }
  .seam__ink--door { display: none; }
  /* the legacy half's one action is a BLOCK, not a run of text in a sentence, and a forced palette collapses the
     colour that normally separates it from the copy around it. The underline survives the theme but says "a link";
     a boundary says "the action". The focus ring still outranks this (.half--legacy a:focus-visible is the more
     specific selector), so focus is never the thing this rule paints over. */
  .sale { outline: 2px solid LinkText; outline-offset: var(--s0); }
  /* the notice is a card the OS repaints to Canvas: the border is the only thing left that says "a card",
     and its two controls are buttons, so they wear the system button pair rather than a fill we chose. */
  #bindNotices .bind-note { border-color: CanvasText; }
  #bindNotices .bind-note__act { color: ButtonText; background: ButtonFace; border-color: ButtonText; }
  #bindNotices .bind-note__x { border-color: ButtonText; }
}

/* ============================================================================================================
   9. THE WORKER'S NOTICE BOX (integrator seam, 2026-09-01)
   sw-client.js CREATES this surface - #bindNotices, .bind-note, .bind-note__t, .bind-note__act, .bind-note__x -
   and its own header says the landing dresses it. Until this block existed no stylesheet in the repo carried
   one of those selectors, so the one thing the update strategy ever shows a person would have rendered as
   unstyled default markup at the end of the document. It is an OPAQUE card on the wall family's own paper:
   it is fixed, so it can come to rest over either half, and it must not borrow the ground it lands on. Both
   controls clear the 44 px floor by min-block-size (ASL Law 5), and there is no width query here at all -
   the box is sized by min(), so LAW 2 has nothing to keep in the page shell.
   ========================================================================================================== */
#bindNotices {
  position: fixed; z-index: 60;
  inset-block-end: calc(var(--s2) + var(--sab)); inset-inline-start: calc(var(--s2) + var(--sal));
  inline-size: min(30rem, calc(100% - var(--s2) * 2 - var(--sal) - var(--sar)));
  display: flex; flex-direction: column; gap: var(--s0);
  pointer-events: none;                       /* the column is a rail; only the notices themselves take a click */
  font-family: var(--font-legible);
}
#bindNotices .bind-note {
  pointer-events: auto;
  display: flex; align-items: center; gap: var(--s1);
  padding: var(--s1) var(--s1) var(--s1) var(--s2);
  background: var(--w-paper); color: var(--w-ink);
  border: 1px solid var(--w-rule); border-inline-start: 3px solid var(--w-accent); border-radius: var(--r1);
}
#bindNotices .bind-note__t {
  margin: 0; flex: 1 1 auto; min-inline-size: 0;
  font-size: var(--fs--1); line-height: 1.45; overflow-wrap: anywhere;
}
#bindNotices .bind-note__act {
  flex: none; min-block-size: var(--target); padding-inline: var(--s2);
  font: inherit; font-size: var(--fs--1);
  color: var(--w-on-accent); background: var(--w-accent);
  border: 1px solid var(--w-accent); border-radius: var(--r1); cursor: pointer;
}
#bindNotices .bind-note__x {
  flex: none; inline-size: var(--target); min-block-size: var(--target);
  display: grid; place-items: center;
  font: inherit; color: var(--w-ink2); background: none;
  border: 1px solid transparent; border-radius: var(--r1); cursor: pointer;
}
/* the dismiss glyph is /icons.js's own "close", appended by sw-client.js as a real <svg> node (class
   "ico ico-close", already 1em); the element is targeted rather than the class so a rename in the icon
   system cannot silently unsize it. */
#bindNotices .bind-note__x svg { inline-size: 1.25em; block-size: 1.25em; }
