/* ==========================================================================
   ROOK - PARTS

   The shared component vocabulary every interior page is built from. Loaded
   after app.css and before stage.css, so the page-level joins in stage.css
   can still override a component without editing it here.

   It has to live in one place. Five pages each inventing their own listing
   row is how a site stops looking like one site.

   The governing constraint is that there is no product photography and there
   will not be for a while, so nothing here waits for a picture. A flavour is
   identified by a colour wash that reads as ink soaked up through the paper,
   a 10px chip and a numeral. Format is a drawn maker's stamp, never a bottle
   shot.

   Two rules worth stating, because breaking either is what would cheapen it:

     Colour identifies, gold interfaces. A flavour tint appears in the wash,
     the chip and the product plate. It never touches a button, a link, a
     focus ring or a rule.

     The wash opacity is capped at .12 on paper and .22 on black. At full
     strength this stops looking like a spirits brand and starts looking like
     a fruit juice brand.
   ========================================================================== */

:root {
  --num:        "Saira", "Raleway", "Arial Narrow", sans-serif;
  --t-title:    clamp(2.5rem, 7vw, 5rem);
  --t-plate:    clamp(2.25rem, 6.5vw, 4.5rem);
  --t-name:     clamp(2.75rem, 6vw, 5.5rem);
  --rail:       8rem;
  --wash-paper: .12;
  --wash-dark:  .22;
  --dusk-h:     clamp(60px, 8vh, 120px);
  --dawn-sm-h:  clamp(48px, 6vh, 90px);
  --ink-dark-2: #CFC6BC;   /* secondary text on black, matches the hero lede */
}

/* --------------------------------------------------------------------------
   THE COLUMN SYSTEM
   Asymmetry is the point. Never split it 6 and 6.
   -------------------------------------------------------------------------- */

.grid12 { display: grid; grid-template-columns: repeat(12, 1fr); column-gap: var(--gutter); row-gap: var(--s6); }
@media (max-width: 900px) { .grid12 { grid-template-columns: repeat(6, 1fr); } }
@media (max-width: 620px) { .grid12 { grid-template-columns: repeat(4, 1fr); } }

/* --------------------------------------------------------------------------
   THE ORDINAL

   One numbering system for the whole site: small, muted, tabular figures. The
   homepage step numerals are deliberately the opposite, big and gold, so the
   two can never be read as the same object.
   -------------------------------------------------------------------------- */

.ord {
  font-family: var(--num); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--track); font-variant-numeric: tabular-nums;
  color: var(--ink-3); transition: color .3s var(--ease);
}
.bay--dark .ord, .plinth .ord, .pdp__plate .ord { color: #9C9188; }

/* The guide band is not part of the range, so it carries rules, not a number. */
.ord--rule { display: inline-block; width: 18px; height: 5px; border-top: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2); }

.sect__eyebrow {
  display: flex; align-items: center; gap: var(--s3);
  font-family: var(--display); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--track); color: var(--ink-3);
  margin-bottom: var(--s5);
}
.bay--dark .sect__eyebrow, .plinth .sect__eyebrow { color: #9C9188; }

/* --------------------------------------------------------------------------
   THE IDENTITY CHIP
   -------------------------------------------------------------------------- */

.chip {
  display: inline-block; width: 10px; height: 10px; flex: 0 0 auto;
  background: var(--f-tint, var(--copper));
  border: 1px solid var(--line-2);
}
.bay--dark .chip, .pdp__plate .chip, .plinth .chip { border-color: rgba(242,239,232,.28); }
.matrix tbody th > .chip { margin-right: var(--s3); }

/* --------------------------------------------------------------------------
   THE FLAVOUR COLOUR FIELD

   Gradient only: no filter, no SVG, nothing that costs a repaint, because it
   repeats once per row. It reads as ink that soaked up through the paper from
   underneath rather than as a coloured panel.
   -------------------------------------------------------------------------- */

.plate__wash {
  position: absolute; left: 0; right: 0; bottom: 0; height: 34%;
  z-index: 0; pointer-events: none;
  opacity: var(--wash-paper);
  background:
    radial-gradient(120% 140% at 22% 128%, var(--f-tint, var(--copper)) 0%, transparent 62%),
    radial-gradient(90% 120% at 74% 136%, var(--f-tint, var(--copper)) 0%, transparent 58%);
}
.pdp__plate .plate__wash { height: 52%; opacity: var(--wash-dark); }

/* --------------------------------------------------------------------------
   THE FLAVOUR BAND

   The one listing component, on every page that lists flavours. Full measure,
   one per row, hairline separated, and containing no bottle.
   -------------------------------------------------------------------------- */

.index { border-top: 1px solid var(--line); }
.index--tail { border-top: 0; }

.plate {
  position: relative; display: grid; gap: var(--s3);
  padding-block: var(--s6); border-bottom: 1px solid var(--line);
  isolation: isolate; overflow: hidden;
}
@media (min-width: 900px) {
  .plate { grid-template-columns: var(--rail) minmax(0, 1fr) 16rem; column-gap: var(--s6); align-items: start; }
}
/* The wash and the smoke canvas are both backdrops and must stay out of the
   grid flow. Miss either and it takes a column, which silently shunts the
   name into the spec column's width and wraps it. */
.plate > *:not(.plate__wash):not(.plate__smoke) { position: relative; z-index: 1; }

.plate__rail { display: flex; align-items: center; gap: var(--s3); }

.plate__name {
  font-family: var(--display); font-size: var(--t-plate); font-weight: 700;
  text-transform: uppercase; line-height: .95; letter-spacing: -.01em;
  color: var(--ink);
}

/* The whole band is one hit area and one tab stop. Everything else inside it
   is inert, which is why .plate__cta is a span. */
.plate__link::after { content: ""; position: absolute; inset: 0; z-index: 2; }

.plate__rule {
  display: block; width: 100%; height: 1px; margin-top: var(--s4);
  background: var(--copper); transform: scaleX(.14); transform-origin: 0 50%;
  transition: transform .42s var(--ease-out);
}

.plate__notes { margin-top: var(--s4); }
.plate__notes li {
  font-family: var(--display); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--track);
  color: var(--ink-3); line-height: 2.1;
}

.plate__body { margin-top: var(--s4); color: var(--ink-2); font-size: var(--t-small); max-width: 52ch; }

.plate__facts .fact { display: flex; justify-content: space-between; gap: var(--s4); padding-block: var(--s2); border-bottom: 1px solid var(--line); }
.plate__facts dt { font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-2); color: var(--ink-3); }
.plate__facts dd { margin: 0; font-family: var(--num); font-size: var(--t-small); font-variant-numeric: tabular-nums; text-align: right; }

.plate__soon { margin-top: var(--s4); font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track); color: var(--copper-ink); }
.plate__cta { display: inline-flex; align-items: center; gap: var(--s2); margin-top: var(--s3); font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track); color: var(--ink); }

/* Hover is a drawn rule and a colour shift. No lift, no shadow, no scale. */
.plate:hover .plate__rule, .plate:focus-within .plate__rule { transform: scaleX(1); }
.plate:hover .ord, .plate:focus-within .ord { color: var(--copper-ink); }

@media (max-width: 640px) {
  .plate__facts { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
  .plate__facts .fact { border-bottom: 0; padding-block: 0; gap: var(--s2); }
  .plate__notes li { display: inline; line-height: 1.9; }
  /* The separator is a drawn hairline, never a punctuation character. */
  .plate__notes li + li::before { content: ""; display: inline-block; width: 14px; height: 1px; background: var(--line-2); vertical-align: middle; margin-inline: var(--s2); }
}

/* --------------------------------------------------------------------------
   THE FORMAT STAMP
   Format is stated by a drawn maker's mark, never by a product shot.
   -------------------------------------------------------------------------- */

.stamp { display: inline-flex; align-items: center; gap: var(--s2); color: var(--line-2); font-family: var(--display); font-size: var(--t-micro); font-weight: 600; letter-spacing: var(--track); text-transform: uppercase; }
.stamp svg { color: currentColor; }
.plate__facts .stamp { color: var(--ink-3); }

/* --------------------------------------------------------------------------
   THE DOT LEADER SPEC ROW
   Twelve pixels of leader is the difference between engineered and
   administrative.
   -------------------------------------------------------------------------- */

.lrows { border-top: 1px solid var(--line); }
.lrow { display: flex; align-items: baseline; gap: var(--s3); padding-block: var(--s3); border-bottom: 1px solid var(--line); }
.lrow__k { font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-2); color: var(--ink-3); white-space: nowrap; }
.lrow__d { flex: 1 1 auto; border-bottom: 1px dotted var(--line-2); transform: translateY(-.3em); }
.lrow__v { font-family: var(--num); font-size: var(--t-small); font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap; }

/* --------------------------------------------------------------------------
   THE INSTRUMENT SCALE

   Was a segmented battery gauge, which read as a game UI and shipped no text
   at all to a screen reader. Now a scale carrying a visible value.
   -------------------------------------------------------------------------- */

.meter { display: grid; grid-template-columns: 6.5rem 1fr 2.75rem; align-items: end; gap: var(--s4); padding-bottom: var(--s2); border-bottom: 1px solid var(--line); }
.meter__label { font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track); color: var(--ink-3); }
.meter__bar { display: flex; align-items: flex-end; justify-content: space-between; height: 16px; }
/* flex:0 0 auto and the radius reset are load bearing. rook.css and app.css
   both set flex:1 on a segment, and app.css rounds it, which stretched these
   into fat rounded blocks: a game health bar rather than an instrument. */
.meter__seg { flex: 0 0 auto; width: 1px; height: 10px; border-radius: 0; background: var(--line-2); }
.meter__seg.is-on, .meter__seg.on { height: 16px; background: var(--copper); }
.meter__v { font-family: var(--num); font-size: var(--t-small); font-variant-numeric: tabular-nums; text-align: right; color: var(--ink); }
.meter__d { color: var(--ink-3); }

/* --------------------------------------------------------------------------
   THE TITLE PAGE

   Replaces the grey band, which was a shop convention. Air before a title is
   the cheapest premium signal there is, and the site had none.
   -------------------------------------------------------------------------- */

/* The first viewport used to be empty cream: a title, a rule and a lede
   stranded in the left third with two thirds of the page dead, and roughly
   600px of vertical space spent saying very little. The title and the
   standfirst now sit side by side on a shared baseline, which uses the width
   the page actually has and gets the first flavour above the fold. */

.phead--index { background: var(--paper); border-bottom: 0; padding-block: var(--s6) var(--s7); }
/* Rows are explicit. Left to auto placement the rule takes a row of its own
   and pushes the standfirst underneath the title, which is the tall empty
   layout this was meant to replace. */
.phead--index .grid12, .phead--index.grid12 { row-gap: 0; }
.phead--index .crumbs { grid-row: 1; grid-column: 1 / -1; margin-bottom: clamp(2rem, 4.5vh, 3.5rem); }
.phead--index .phead__title { grid-row: 2; grid-column: 1 / span 7; margin-top: 0; font-family: var(--display); font-size: var(--t-title); font-weight: 700; text-transform: uppercase; line-height: .94; letter-spacing: -.022em; }
.phead--index .phead__lede { grid-row: 2; grid-column: 8 / span 5; align-self: end; margin-top: 0; padding-bottom: .5em; font-size: 1.0625rem; color: var(--ink-2); max-width: 44ch; }
.phead--index .phead__rule { grid-row: 3; grid-column: 1 / -1; position: relative; display: block; margin-top: var(--s5); height: 1px; background: var(--line); transform-origin: 0 50%; }
.phead--index .phead__rule::before { content: ""; position: absolute; left: 0; top: 0; width: 96px; height: 2px; background: var(--copper); }

@media (max-width: 900px) {
  .phead--index .phead__title, .phead--index .phead__lede { grid-column: 1 / -1; }
  .phead--index .phead__lede { margin-top: var(--s5); padding-bottom: 0; }
}

/* --------------------------------------------------------------------------
   THE BLACK FOOT

   Paper never meets the black footer at a hard edge. The waitlist band and
   the footer read as one continuous base separated by a single gold hairline,
   so the page visibly sits on something.
   -------------------------------------------------------------------------- */

.dusk { height: var(--dusk-h); margin-bottom: -1px; background: linear-gradient(180deg, var(--paper) 0%, #6E6960 28%, #171613 62%, var(--dark) 100%); }
.dawn--sm { height: var(--dawn-sm-h); }

.plinth { position: relative; background: var(--dark); color: var(--paper); overflow: hidden; isolation: isolate; padding-block: var(--s10) var(--s9); }
.plinth > .wrap { position: relative; z-index: 2; }
.plinth__t { font-family: var(--display); font-size: var(--t-title); font-weight: 700; text-transform: uppercase; line-height: 1; letter-spacing: -.01em; max-width: 16ch; }
.plinth__p { margin-top: var(--s5); max-width: 46ch; color: var(--ink-dark-2); }
.plinth__fine { margin-top: var(--s5); font-size: var(--t-micro); color: #8F857C; max-width: 52ch; }

.plinth .signup { margin-top: var(--s7); max-width: 520px; }
.plinth .signup__row { display: flex; gap: var(--s3); }
.plinth .signup__row .input { flex: 1 1 auto; min-width: 0; background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.2); color: var(--paper); }
.plinth .signup__row .input::placeholder { color: #8F857C; }
.plinth .signup__row .input:focus { border-color: var(--copper); background: rgba(255,255,255,.08); }
.plinth .signup__row .btn { flex: 0 0 auto; white-space: nowrap; }
.plinth .field__label { color: var(--copper-2); }

.plinth + .ftr { padding-top: var(--s7); border-top: 1px solid rgba(184,152,90,.4); }

@media (max-width: 520px) {
  .plinth .signup__row { flex-direction: column; align-items: stretch; }
  .plinth .signup__row .btn { width: 100%; }
}

/* --------------------------------------------------------------------------
   THE JOURNAL INDEX ROW
   Three articles as three well set lines beats three empty grey rectangles
   where hero images should be.
   -------------------------------------------------------------------------- */

.ledger { border-top: 1px solid var(--line); }
.ledger__row { position: relative; display: grid; gap: var(--s3); padding-block: var(--s6); border-bottom: 1px solid var(--line); transition: border-color .3s var(--ease); }
@media (min-width: 900px) { .ledger__row { grid-template-columns: var(--rail) minmax(0, 1fr) minmax(0, 34ch) 3rem; column-gap: var(--s6); align-items: baseline; } }
.ledger__title { font-family: var(--display); font-size: var(--t-h2); font-weight: 700; text-transform: uppercase; letter-spacing: .02em; }
.ledger__ex { color: var(--ink-2); font-size: var(--t-small); }
.ledger__go { justify-self: end; color: var(--ink-3); transition: color .3s var(--ease), transform .3s var(--ease); }
.ledger__row a::after { content: ""; position: absolute; inset: 0; }
.ledger__row:hover { border-bottom-color: var(--copper); }
.ledger__row:hover .ord { color: var(--copper-ink); }
.ledger__row:hover .ledger__go { color: var(--copper-ink); transform: translateX(4px); }

/* --------------------------------------------------------------------------
   THE DECISION TABLE

   A real table, scored, with a caption. The most convincing engineered moment
   on the site, and it needs no photography whatsoever. It scrolls rather than
   restructuring, so there is one layout to reason about instead of two.
   -------------------------------------------------------------------------- */

.tablewrap { overflow-x: auto; }
.matrix { width: 100%; min-width: 720px; border-collapse: collapse; }
.matrix th, .matrix td { padding: var(--s4) var(--s4) var(--s4) 0; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
.matrix thead th { font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track); color: var(--ink-3); border-bottom-color: var(--line-2); }
.matrix tbody th { font-family: var(--display); font-size: var(--t-h3); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.matrix .meter { grid-template-columns: 1fr 2.25rem; border-bottom: 0; padding-bottom: 0; }
.matrix .meter__label { display: none; }
.matrix__cta { font-family: var(--display); font-size: var(--t-micro); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track); color: var(--copper-ink); white-space: nowrap; }

/* --------------------------------------------------------------------------
   THE CROSS-SELL ROW
   -------------------------------------------------------------------------- */

.strip { border-top: 1px solid var(--line); }
.strip__it { position: relative; display: flex; align-items: center; gap: var(--s4); padding-block: var(--s5); border-bottom: 1px solid var(--line); font-family: var(--display); font-size: var(--t-h2); font-weight: 700; text-transform: uppercase; letter-spacing: .02em; transition: color .3s var(--ease); }
.strip__n { flex: 1 1 auto; }
.strip__go { flex: 0 0 auto; color: var(--ink-3); transition: transform .3s var(--ease), color .3s var(--ease); }
.strip__it:hover { color: var(--copper-ink); }
.strip__it:hover .strip__go { transform: translateX(4px); color: var(--copper-ink); }

/* --------------------------------------------------------------------------
   THE NUMBERED DARK COLUMNS

   Replaces three boxes. Bare numerals divided by hairlines. The numeral is
   big and gold precisely so it cannot be confused with the .ord system.
   -------------------------------------------------------------------------- */

.cols { display: grid; gap: var(--s7); }
@media (min-width: 860px) {
  .cols { grid-template-columns: repeat(3, 1fr); gap: 0; }
  .cols__i { padding-inline: var(--s7); border-left: 1px solid var(--line-dark); }
  .cols__i:first-child { padding-left: 0; border-left: 0; }
  .cols__i:last-child { padding-right: 0; }
}
.cols__n { font-family: var(--num); font-size: clamp(2.5rem, 5vw, 4rem); font-weight: 600; line-height: 1; color: var(--copper-2); font-variant-numeric: tabular-nums; }
.cols__h { margin-top: var(--s4); font-family: var(--display); font-size: var(--t-h3); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--paper); }
.cols__p { margin-top: var(--s3); color: var(--ink-dark-2); font-size: var(--t-small); max-width: 34ch; }

/* --------------------------------------------------------------------------
   THE TICKER ON PAPER
   -------------------------------------------------------------------------- */

.brands--paper { background: var(--paper); border-block: 1px solid var(--line); }
.brands--paper .brands__b { color: var(--ink-3); }
.brands--paper .brands__b:hover { color: var(--copper-ink); }

/* --------------------------------------------------------------------------
   THE FOOTER

   The markup and the stylesheet had drifted apart: rook.css styles .ftr__top,
   .ftr__bottom and `.ftr h3`, but the markup emits .ftr__grid, .ftr__base and
   `h2.ftr__h`. Nothing matched, so the footer was an unstyled stack of links
   on every page on the site. This is the footer the markup actually renders.
   -------------------------------------------------------------------------- */

.ftr__grid { display: grid; gap: var(--s7); padding-bottom: var(--s7); }
@media (min-width: 900px) { .ftr__grid { grid-template-columns: 1.7fr 1fr 1fr 1fr auto; gap: var(--s6); } }

.ftr__h {
  margin-bottom: var(--s4);
  font-family: var(--display); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--track); color: var(--paper);
}
.ftr__col ul { display: grid; gap: var(--s2); }
.ftr__brand { max-width: 34ch; }

.ftr__icons { display: flex; gap: var(--s3); }
.ftr__icons a {
  display: grid; place-items: center; width: 34px; height: 34px;
  border: 1px solid rgba(255,255,255,.22); color: #B5A79B;
  transition: border-color .25s var(--ease), color .25s var(--ease);
}
.ftr__icons a:hover { border-color: var(--copper); color: var(--copper-2); }

.ftr__base {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--s3) var(--s5);
  padding-top: var(--s5); border-top: 1px solid var(--line-dark);
}
.ftr__legal { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); font-size: var(--t-micro); color: #857A70; }

/* --------------------------------------------------------------------------
   THE MOBILE MENU

   Same drift: rook.css styles .menu__list, the markup emits .menu__in. The
   panel opened to a column of unstyled links.
   -------------------------------------------------------------------------- */

.menu__in { display: grid; align-content: start; }
.menu__in a {
  display: block; padding-block: var(--s4); border-bottom: 1px solid var(--line);
  font-family: var(--display); font-size: 1.125rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--track-2);
}
.menu__in a:hover { color: var(--copper-ink); }

/* The product page cross-sell section closes the page on paper. */
.pdp__also { padding-block: var(--bay); }
.plinth__in { position: relative; z-index: 2; }

/* ==========================================================================
   ATMOSPHERE

   The pages were structurally right and still read as a wireframe. Three
   reasons, all of them fixable without touching a line of markup:

     There was one typeface doing every job, so nothing had contrast against
     anything else.

     The ground was a flat fill. Premium print has tooth; a screen imitating
     paper with a solid hex reads as a document, not as a brand.

     The flavour wash was capped so low it was invisible, which meant five
     flavours looked identical and the one piece of colour identity the site
     owns did no work at all.
   ========================================================================== */

/* --- Paper tooth ----------------------------------------------------------

   Fractal noise over the whole viewport, fixed so it behaves like grain in
   the paper rather than a texture glued to the content. It is a data URI, so
   it costs no request, and it sits above everything with pointer-events off
   so it can never intercept a click. Roughly 3%: felt, not seen. */

body::after {
  content: "";
  position: fixed; inset: 0; z-index: 9998; pointer-events: none;
  opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
}
@media print { body::after { display: none; } }

/* --- The wash, made to actually work --------------------------------------

   It was a 34% band at .12, which on a warm paper ground is indistinguishable
   from nothing. Now it is a tall soft field rising from the lower left, so a
   flavour is legible as a colour the moment you look at the row, and the
   whole band tilts fractionally warm or cool rather than being decorated in
   one corner. Still well under the level where it would read as fruit juice. */

.plate__wash {
  height: 100%;
  opacity: .17;
  background:
    radial-gradient(78% 118% at 6% 104%, var(--f-tint, var(--copper)) 0%, transparent 64%),
    radial-gradient(52% 88% at 88% 118%, var(--f-tint, var(--copper)) 0%, transparent 60%);
  transition: opacity .5s var(--ease-out);
}
.plate:hover .plate__wash, .plate:focus-within .plate__wash { opacity: .3; }

/* --- The ghost numeral ----------------------------------------------------

   A large index figure sitting behind each band. It is what turns a list of
   rows into a catalogue, and it is drawn with a CSS counter, so it needs no
   markup change and cannot fall out of step with the rail numbers: both count
   the same DOM.

   Hidden from assistive tech by being generated content on a decorative
   pseudo-element, and hidden below 900px where there is no room for it. */

.index { counter-reset: plate; }
.plate { counter-increment: plate; }

@media (min-width: 900px) {
  .plate::before {
    content: counter(plate, decimal-leading-zero);
    position: absolute; right: -.06em; bottom: -.34em;
    z-index: 0; pointer-events: none;
    font-family: var(--num);
    font-size: clamp(9rem, 17vw, 15rem);
    font-weight: 700; line-height: .74;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
    opacity: .045;
    transition: opacity .5s var(--ease-out), transform .7s var(--ease-out);
  }
  .plate:hover::before, .plate:focus-within::before { opacity: .08; transform: translateX(-8px); }
  .plate--guide::before { content: none; }
}

/* --- Typographic contrast -------------------------------------------------

   Raleway was doing display and body both, which is why the hierarchy read
   flat. Saira now carries everything technical: numerals, labels, spec
   values, tabs. Raleway keeps the names and the reading copy. Two registers,
   one of them wide and mechanical, and suddenly the page has structure. */

.plate__name { letter-spacing: -.022em; }
.plate__notes li { font-family: var(--num); letter-spacing: .16em; line-height: 2.3; color: var(--ink-2); }
.plate__soon,
.plate__cta,
.sect__eyebrow,
.shead__tab,
.crumbs { font-family: var(--num); }
.lrow__k, .meter__label, .plate__facts dt { font-family: var(--num); }

/* The eyebrow gets a rule so a section starts on a mark, not on air. */
.sect__eyebrow::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--line); margin-left: var(--s3); }

/* --- Rhythm ---------------------------------------------------------------
   Bands were uniform, which made a long index monotonous. A touch more room
   and a heavier first rule give the list a top and a cadence. */

.plate { padding-block: clamp(2.25rem, 4.5vw, 3.75rem); }
.index { border-top-width: 2px; border-top-color: var(--ink); }

/* --- The title page, with the rule doing something ------------------------ */

.phead--index .phead__rule::before { width: 96px; height: 2px; top: -1px; }

/* ==========================================================================
   THE FLAVOUR PLATE, REBUILT

   The listing was hairline rows on cream with a pale tint smudged into one
   corner. Five of them looked like a spreadsheet with a gradient applied, and
   the tints - pink, lilac, yellow on warm paper - read as a slide deck.

   The site owns exactly one genuinely expensive thing: a volumetric smoke
   shader that is also, literally, the logo mark. It was being used once, in
   the hero, and then the pages fell back to CSS gradients.

   So a flavour is now a dark object laid on the paper with its own live
   smoke in the brand's tint. The page ground stays light and frames them, so
   the site reads light overall while each flavour is something to look at.
   Every plate is the same material as the opener, because it is literally the
   same shader.
   ========================================================================== */

.index { border-top: 0; counter-reset: plate; }

.plate {
  background: #0B0B0D;
  color: var(--paper);
  border-bottom: 0;
  margin-block: clamp(1.5rem, 3vw, 3rem);
  padding: clamp(2rem, 4vw, 4rem);
  /* A flavour owns the screen rather than occupying a row. At 300px these
     read as a list with pictures; at three quarters of the viewport, moving
     through the range feels like a sequence of scenes. */
  min-height: clamp(420px, 74svh, 760px);
  align-items: end;
  overflow: hidden;
}

/* The live canvas, and the CSS gradient that stays underneath it forever as
   the fallback for no WebGL, a lost context or a failed compile. */
.plate__smoke {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  display: block; pointer-events: none;
  opacity: 0; transition: opacity 1.1s var(--ease-out);
}
.plate__smoke.is-live { opacity: 1; }

.plate__wash { height: 100%; opacity: .38; }
.plate:hover .plate__wash, .plate:focus-within .plate__wash { opacity: .5; }

/* A scrim under the type. The smoke leans left, which is exactly where the
   name sits, so contrast cannot be left to whatever the shader is doing. */
.plate::after {
  content: "";
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, rgba(6,6,8,.72) 0%, rgba(6,6,8,.46) 38%, rgba(6,6,8,.30) 66%, rgba(6,6,8,.52) 100%);
}
.plate > *:not(.plate__wash):not(.plate__smoke) { z-index: 2; }

/* Type reversed out. */
.plate__name { color: var(--paper); letter-spacing: -.025em; }
.plate .ord { color: rgba(242,239,232,.55); }
.plate .chip { border-color: rgba(242,239,232,.4); }
.plate__notes li { color: rgba(242,239,232,.62); }
.plate__body { color: rgba(242,239,232,.66); }
.plate__facts .fact { border-bottom-color: rgba(242,239,232,.14); }
.plate__facts dt { color: rgba(242,239,232,.45); }
.plate__facts dd { color: var(--paper); }
.plate__soon { color: var(--copper-2); }
.plate__cta { color: var(--paper); }
.plate__rule { background: var(--copper-2); }

/* Composition.
 *
 * The three column grid was inherited from the old hairline row, where a
 * narrow rail carried the number. On a dark plate that rail became 128px of
 * nothing with a 10px chip floating alone in it, and the name started at an
 * arbitrary 333px aligned to no edge at all. It looked like a bug because it
 * was one.
 *
 * Two columns now. The number and chip sit directly above the name as a
 * caption line, the name starts hard on the plate's own padding edge, and the
 * spec column holds the right and sits on the same baseline as the name.
 */
@media (min-width: 900px) {
  .plate {
    grid-template-columns: minmax(0, 1fr) 17rem;
    grid-template-areas:
      "rail side"
      "main side";
    align-content: end;
    row-gap: var(--s4);
  }
  .plate__rail { grid-area: rail; }
  .plate__main { grid-area: main; }
  .plate__side { grid-area: side; align-self: end; }

  /* The ghost figure was clipped by the plate edge and read as a rendering
     fault. With the ordinal back in the rail it was saying the same thing
     twice anyway, so it goes. */
  .plate::before { content: none; }
}

/* The guide band is not a flavour, so it stays on paper: it is the one row in
   the index that is a signpost rather than a product. */
.plate--guide {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line-2);
  min-height: 0;
}
.plate--guide::after { content: none; }
.plate--guide .plate__name { color: var(--ink); }
.plate--guide .plate__body { color: var(--ink-2); }
.plate--guide .plate__cta { color: var(--ink); }
.plate--guide .ord { color: var(--ink-3); }
.plate--guide .plate__rule { background: var(--copper); }

/* The product page plate. Same material as the listing plates and the opener,
   at the size the page is actually built around. It was a flat black
   rectangle, which is a poor thing for the one page whose job is to sell the
   flavour. */
.pdp__plate { position: relative; overflow: hidden; isolation: isolate; }
.pdp__plate .plate__smoke { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; }
.pdp__plate .plate__wash { z-index: 0; }
/* Light touch. This plate is portrait and the smoke has less room than in a
   listing row, so the scrim only has to protect the name at the foot. An
   earlier version ran to .78 across the whole thing and erased the smoke,
   which is the same mistake the hero floor made. */
.pdp__plate::after {
  content: "";
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(6,6,8,.1) 0%, rgba(6,6,8,0) 38%, rgba(6,6,8,.58) 100%);
}
.pdp__plate-in { position: relative; z-index: 2; }

/* --------------------------------------------------------------------------
   SCROLL TIMELINES NEED THIS

   rook.css sets overflow-x:hidden on body to stop sideways scroll. That also
   makes body a scroll container, and a view() timeline resolves against the
   nearest scrollport ancestor - so every scroll-driven animation on the site
   measured itself against a box that never scrolls while the document scrolled
   somewhere else. They all froze at a fixed progress, silently: the transforms
   were applied, they just never advanced. It looked like the animations had
   simply not been written.

   overflow-x:clip does the same clipping without creating a scroll container.
   Guarded, because a browser without clip should keep the hidden it has.
   -------------------------------------------------------------------------- */

@supports (overflow: clip) {
  body { overflow-x: clip; }
}

/* ==========================================================================
   DEPTH AND CHOREOGRAPHY

   The single reason this read as competent rather than costly: everything sat
   on one plane and nothing responded to scroll. A page where the only motion
   is a fade-in is a document. Depth is what money looks like.

   All of it is scroll-driven CSS, so the browser runs it on the compositor
   with no JavaScript, no scroll listener and no jank. Browsers without
   animation-timeline get the finished, static composition, which is the
   design we already had rather than a broken one.
   ========================================================================== */

/* The parallax is NOT done here.
 *
 * It was, with animation-timeline: view(), and it silently did nothing: the
 * animations attached, reported playState "running", and their currentTime
 * stayed null forever because body is a scroll container and the timeline
 * never resolved against the scroller that actually moves. Every plate showed
 * an identical frozen transform.
 *
 * Rather than keep fighting which element owns the scrollport, the drift now
 * happens inside the shader in plate-smoke.js, driven by each plate's real
 * position on screen. There is already a rAF loop running for the visible
 * plates, so it costs one uniform and no DOM work at all - and being in the
 * shader it moves the smoke itself rather than sliding a bitmap, which is the
 * difference between depth and a moving texture.
 *
 * The plates carry .rv, so their entrance still comes from the observer in
 * rook.js, which works.
 */

/* --- Scale and grid-breaking ----------------------------------------------

   Perfect containment reads as a template. The name now runs to the optical
   edge of the plate and overhangs its own padding slightly, which is the
   difference between type placed in a box and type that owns the object. */

.plate__name {
  font-size: clamp(2.75rem, 7.2vw, 6.5rem);
  line-height: .88;
  letter-spacing: -.035em;
}
@media (min-width: 900px) {
  .plate__name { margin-left: -.055em; }   /* optical, not metric, alignment */
}

@media (prefers-reduced-motion: reduce) {
  .plate__smoke { transition: none; }
}

/* Type over live smoke.
 *
 * The smoke is generated and it drifts, so no fixed scrim can know where it
 * will be bright. Three passes of shadow keep every string legible wherever
 * the density lands, and let the scrim stay light enough that the artwork
 * survives. Cheaper and more reliable than darkening half the plate.
 */
/* Scoped to the dark plate only. Unscoped, .plate__notes li also matched the
   product page info column, which sits on paper - and a shadow tuned for
   white type on smoke turns black type on cream into blurred embossing. */
.plate .plate__name,
.plate .plate__notes li,
.plate .plate__body,
.plate .plate__soon,
.plate .plate__cta,
.plate .plate__facts dt,
.plate .plate__facts dd,
.plate .ord {
  text-shadow: 0 1px 2px rgba(4,4,6,.55), 0 2px 14px rgba(4,4,6,.45), 0 0 42px rgba(4,4,6,.35);
}
.plate--guide .plate__name,
.plate--guide .plate__body,
.plate--guide .plate__cta,
.plate--guide .ord { text-shadow: none; }
