/* ============================================================
   Farpak — the board
   ------------------------------------------------------------
   The parent site is an architect's presentation board: a sheet
   of chipboard with the studio's two products mounted on it as
   material samples, dimensioned and annotated.

   That is not decoration. Each product owns a different visual
   material (Duelight is Liquid Glass; Darkside is true black),
   and a board is the one format that can hold two materials side
   by side without averaging them into a house style. Every
   number written on this page is a real number from the products.

   Graphite on chipboard. One drafting red, used as a line.
   ============================================================ */

/* ── Reset ─────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Tokens ────────────────────────────────────────────────── */

:root {
    /* The board. Chipboard grey-green — cooler and a full step
       darker than paper, so ink sits *on* it rather than glowing. */
    --board:       #d8d6cc;
    --board-lift:  #e3e1d8;   /* a mounted sheet, raised off the board */
    --board-sink:  #c5c3b7;   /* the recess a sample is set into */

    /* Pencil weights. Three, like a real drawing: line, note, dimension.
       Ratios are quoted against --board-sink, the darkest ground any of
       them lands on, because a value that only clears AA on the lightest
       sheet is a value that fails somewhere on the page. */
    --ink:    #17191b;   /* 10.1:1 on sink, 12.5:1 on board */
    --ink-2:  #3f4341;   /*  5.7:1 on sink */
    --ink-3:  #494d4b;   /*  4.9:1 on sink — smallest text allowed */
    --hair:   rgba(23, 25, 27, 0.22);   /* rules only, never text */
    --hair-2: rgba(23, 25, 27, 0.11);

    /* Drafting red. A markup pencil: lines, marks, one live state.
       -ink is the darkened cut for text small enough to need 4.5:1. */
    --redline:     #c8321f;
    --redline-ink: #a82717;

    /* The two materials, quoted at chip size on the board. */
    --tf-blue:   #2f6dff;
    --tf-purple: #8b46f0;

    --rail:  46px;              /* the sheet header */
    --gutter: clamp(20px, 4.6vw, 76px);
    --sheet:  1200px;

    --sans: 'Archivo', ui-sans-serif, system-ui, -apple-system, sans-serif;
    --mono: 'Fragment Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Drawing ease: a drawn line accelerates off the ruler and
       decelerates into the arrowhead. */
    --draw: cubic-bezier(0.16, 1, 0.3, 1);

    /* The press. Feedback belongs on pointer-down, and the moment lag
       appears directness falls off a cliff — so this is the one duration
       on the page short enough to read as "now" rather than as motion. */
    --press: 90ms;
}

/* ── Ground ────────────────────────────────────────────────── */

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--rail) + 24px);
    /* `clip` rather than `hidden`, and here rather than on <body>. The
       enlarged wordmark reaches well past the right edge and would otherwise
       widen the scrollable area; `hidden` on <body> would fix that but also
       compute overflow-y to auto, making <body> a scroll container and
       breaking the sticky positioning the wordmark depends on. `clip`
       creates no scroll container at all. */
    overflow-x: clip;
}

body {
    font-family: var(--sans);
    font-variation-settings: 'wdth' 100;
    background: var(--board);
    color: var(--ink);
    /* 17px at the browser's default, but stated relatively so a reader who
       has raised their base text size actually gets it. A px body size is a
       silent override of that setting. */
    font-size: 1.0625rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

    /* The tooth of the board. Two offset dot fields at low alpha —
       enough to stop the ground reading as flat #hex, never enough
       to notice as a pattern. */
    background-image:
        radial-gradient(rgba(23, 25, 27, 0.035) 0.5px, transparent 0.5px),
        radial-gradient(rgba(255, 255, 255, 0.4) 0.5px, transparent 0.5px);
    background-size: 4px 4px, 4px 4px;
    background-position: 0 0, 2px 2px;
}

a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:focus-visible {
    outline: 2px solid var(--redline);
    outline-offset: 3px;
    border-radius: 1px;
}

::selection { background: var(--redline); color: #fff; }

/* ── Type scale ────────────────────────────────────────────── */

/* Sheet titles run narrow, the way lettering is compressed to fit a
   title strip. The width axis does the compressing, not a transform. */
.t-sheet {
    font-size: clamp(2.6rem, 7.4vw, 5.6rem);
    font-variation-settings: 'wdth' 82;
    font-weight: 600;
    line-height: 0.96;
    letter-spacing: -0.03em;
    text-wrap: balance;
}

.t-head {
    font-size: clamp(1.7rem, 3.4vw, 2.7rem);
    font-variation-settings: 'wdth' 88;
    font-weight: 600;
    line-height: 1.08;
    letter-spacing: -0.022em;
    text-wrap: balance;
}

.t-sub {
    font-size: clamp(1.02rem, 1.5vw, 1.18rem);
    color: var(--ink-2);
    line-height: 1.62;
    max-width: 46ch;
}

.t-body { color: var(--ink-2); max-width: 68ch; }

/* Drafting annotation. Monospace here is measurement, not costume:
   every string set in it is a dimension, a mark, or a sheet code. */
.t-note {
    font-family: var(--mono);
    font-size: 0.688rem;
    line-height: 1.5;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.t-dim {
    font-family: var(--mono);
    font-size: 0.75rem;
    letter-spacing: 0.02em;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

.mark { color: var(--redline-ink); }

/* ── The sheet header ──────────────────────────────────────── */

.rail {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 90;
    height: var(--rail);
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 0 var(--gutter);
    background: rgba(216, 214, 204, 0.86);
    -webkit-backdrop-filter: saturate(150%) blur(14px);
    backdrop-filter: saturate(150%) blur(14px);
}

/* A scroll edge, not a rule.
   ------------------------------------------------------------------
   A 1px border under floating chrome draws itself whether or not there
   is anything beneath it to separate from — at the top of the page it
   is a line dividing the rail from empty board. This fades in only once
   content has actually travelled under the rail, and it is a gradient
   rather than a hairline because what it is describing is the chrome
   floating above the sheet, not a join between two panels.

   Ink rather than a ground colour: the sheets alternate between --board
   and --board-lift, and a soft shadow reads correctly over both. */
.rail::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: 12px;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(to bottom, rgba(23, 25, 27, 0.13), rgba(23, 25, 27, 0));
    transition: opacity 0.28s var(--draw);
}

.scrolled .rail::after { opacity: 1; }

.rail-mark {
    font-variation-settings: 'wdth' 78;
    font-weight: 700;
    font-size: 1.06rem;
    letter-spacing: 0.02em;
    padding-right: 20px;
    border-right: 1px solid var(--hair);
    align-self: stretch;
    display: flex;
    align-items: center;
    gap: 0.5em;
}

/* The mark — Darkside's own bezel profile read as an F, inline so it takes
   the room's ink through currentColor. It stands taller than the wordmark's
   cap height on purpose: at the same height a letter F immediately before
   the word FARPAK reads as part of it. */
.rail-glyph {
    flex: none;
    height: 0.90em;
    width: auto;
    fill: currentColor;
}

.rail-nav { display: flex; gap: 4px; margin-right: auto; }

.rail-nav a {
    position: relative;
    font-family: var(--mono);
    font-size: 0.688rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-3);
    padding: 6px 10px;
    border-radius: 2px;
    transition: color 0.2s, background 0.2s;
}

/* Hit padding, not visual padding. The label is small because a sheet index
   is small; the target it answers to is not. This takes the box to the full
   height of the rail without moving a pixel of ink — which is the difference
   between a tidy row of labels and a row you can actually hit on a tablet. */
.rail-nav a::after {
    content: '';
    position: absolute;
    inset: -9px -2px;
}

.rail-nav a:hover { color: var(--ink); background: rgba(23, 25, 27, 0.06); }

/* The sheet you are on gets the revision tick a draughtsman
   would put beside the active sheet in the index. */
.rail-nav a[aria-current='true'] { color: var(--ink); }
.rail-nav a[aria-current='true']::before {
    content: '';
    display: inline-block;
    width: 5px;
    height: 5px;
    margin-right: 7px;
    vertical-align: 1px;
    background: var(--redline);
}

.rail-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    font-family: var(--mono);
    font-size: 0.688rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

.rail-meta .sep { width: 1px; height: 13px; background: var(--hair); }

/* ── Sheet layout ──────────────────────────────────────────── */

.sheet { padding: clamp(72px, 9vw, 132px) var(--gutter); position: relative; background: var(--board); }
.band { padding-bottom: clamp(80px, 9.5vw, 140px); }
.sheet-inner { max-width: var(--sheet); margin: 0 auto; }

/* Sheets alternate ground so the set reads as separate drawings
   rather than one long scroll. */
.sheet--lift { background: var(--board-lift); }
.sheet + .sheet { border-top: 1px solid var(--hair); }

/* The header strip of a sheet: title left, sheet code right, one
   rule under both — the way a drawing titles itself. */
.sheet-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 24px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--ink);
    margin-bottom: clamp(38px, 5vw, 62px);
}

.sheet-head .t-dim { flex: none; }

/* ── Cover sheet ───────────────────────────────────────────── */

.cover {
    min-height: 100svh;
    padding-top: calc(var(--rail) + clamp(24px, 4.6vh, 60px));
    padding-bottom: clamp(36px, 5vh, 64px);
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    text-align: center;
}

.cover-inner { width: 100%; max-width: var(--sheet); margin: 0 auto; }

/* The studio's name, set the way a project title is set on a board.
   ------------------------------------------------------------------
   FARPAK carries the size; STUDIOS sits under it at a fraction of the
   height and is letterspaced out to exactly FARPAK's width — measured by
   js/board.js rather than guessed, so the two stay flush at every size and
   after the webfont lands. On arrival the second line opens to that width,
   which is the only motion the cover has and the only one it needs. */
.wordmark {
    margin: 0 0 clamp(22px, 3.4vh, 40px);
    font-variation-settings: 'wdth' 78;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--ink);
    line-height: 0.86;
}

.wordmark .wm-line { display: block; }

.wordmark .wm-1 {
    display: inline-block;
    font-size: clamp(3.1rem, 12.4vw, 10rem);
    letter-spacing: -0.018em;
}

/* Much smaller, and tracked out by the script to exactly the width of the
   line above. The static values here are what a reader without JavaScript
   gets: a sensible spread rather than a flush one. */
.wordmark .wm-2 {
    display: inline-block;
    margin-top: clamp(3px, 0.6vh, 9px);
    font-size: clamp(0.72rem, 1.7vw, 1.3rem);
    font-weight: 600;
    font-variation-settings: 'wdth' 96;
    color: var(--ink-2);
    letter-spacing: 0.42em;
    margin-right: -0.42em;
    white-space: nowrap;
}

/* With the script running it opens to the measured width instead. */
.js .wordmark .wm-2 { opacity: 0; }

.cover-claim {
    font-size: clamp(1.34rem, 2.6vw, 2.15rem);
    font-variation-settings: 'wdth' 92;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.026em;
    max-width: 24ch;
    margin: 0 auto clamp(16px, 2.2vw, 24px);
    text-wrap: balance;
}

/* The surprising clause gets the pencil the rest of the page reserves
   for marks. */
.cover-claim em { font-style: normal; color: var(--redline-ink); }

.cover-lede {
    font-size: clamp(0.97rem, 1.1vw, 1.05rem);
    color: var(--ink-2);
    line-height: 1.55;
    max-width: 44ch;
    margin: 0 auto clamp(22px, 3vw, 32px);
}

.cover-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 10px 22px;
    padding-bottom: clamp(24px, 3.4vw, 44px);
    margin-bottom: clamp(24px, 3.4vw, 44px);
    position: relative;
}

/* The rule under the cover is drawn rather than declared, so it can arrive
   the way every other line on this site does: along its own length. */
.cover-actions::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: left center;
}

.js .cover-actions::after { transition: transform 1.05s 0.42s var(--draw); }
.lit .cover-actions::after { transform: scaleX(1); }
.no-js .cover-actions::after, html:not(.js) .cover-actions::after { transform: scaleX(1); }

/* The samples come up like a print in a tray: out of focus, then resolved.
   One shot, on the cover only, and the filter is dropped the moment it lands
   so nothing carries a blur through the rest of the page's life. */
.js .samples .sample { opacity: 0; filter: blur(7px); }

.lit .samples .sample {
    opacity: 1;
    filter: blur(0);
    transition: opacity 0.95s 0.6s var(--draw), filter 1.1s 0.6s var(--draw);
}
.lit .samples .sample:nth-child(2) { transition-delay: 0.74s; }


/* ── Buttons ───────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 46px;
    padding: 12px 22px;
    font-size: 0.938rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    border-radius: 2px;
    transition: background 0.22s, color 0.22s, border-color 0.22s, transform 0.22s var(--draw);
}

.btn-solid { background: var(--ink); color: var(--board-lift); }
/* The red arrives as a rule under the label, not as a fill: this page spends
   its one colour on lines. */
.btn-solid:hover {
    background: #000;
    box-shadow: inset 0 -2px 0 var(--redline);
    transform: translateY(-1px);
}

.btn-line { border: 1px solid var(--ink); color: var(--ink); }
.btn-line:hover { background: var(--ink); color: var(--board-lift); transform: translateY(-1px); }

/* The press.
   ------------------------------------------------------------------
   Feedback on pointer-down, not on release. Hover is a desktop
   affordance and the App Store link on this page is followed mostly on
   a phone, where nothing whatsoever happened between touching a button
   and the next page arriving.

   The board presses rather than bounces: it is graphite on card, not
   glass, so the button takes the weight of the finger and gives none of
   it back. `:active` is placed after the hovers deliberately — equal
   specificity, later in source, so a pressed button stops lifting. */
.btn:active {
    transform: translateY(0) scale(0.984);
    transition-duration: var(--press);
}

.btn-solid:active { background: #000; box-shadow: inset 0 -2px 0 var(--redline); }
.btn-line:active { background: var(--ink); color: var(--board-lift); }

/* The leader line commits to full length on the press, so a touch reader
   sees the same drawn gesture a pointer gets on approach. */
.btn-lead:active { color: var(--redline-ink); }
.btn-lead:active::after { transform: scaleX(1); transition-duration: var(--press); }

.rail-nav a:active { color: var(--ink); background: rgba(23, 25, 27, 0.1); transition-duration: var(--press); }
.block-cell dd a:active,
.back-live:active { color: var(--redline-ink); transition-duration: var(--press); }

/* A text action with the leader line a drawing uses to point at
   something. The line draws itself on approach. */
.btn-lead {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    font-size: 0.938rem;
    font-weight: 500;
    color: var(--ink-2);
    transition: color 0.22s;
}

/* Scaled rather than widened: growing a `width` reflows the line's
   neighbours every frame for the sake of 14 pixels. */
.btn-lead::after {
    content: '';
    width: 34px;
    height: 1px;
    background: currentColor;
    transform: scaleX(0.59);
    transform-origin: left center;
    transition: transform 0.3s var(--draw);
}

.btn-lead:hover { color: var(--redline-ink); }
.btn-lead:hover::after { transform: scaleX(1); }

/* ── Material samples ──────────────────────────────────────── */

/* The signature of the page. Two products mounted as physical
   samples: one of Liquid Glass, one of true black. Each is set into
   a recess in the board, dimensioned, and links into a page built
   from that same material. */

.samples { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 2.4vw, 34px); }

/* A sample is set *into* the board, not laid on top of it: the inner
   shadow is the recess the swatch is dropped into. */
.sample {
    position: relative;
    display: block;
    padding: 12px 12px 0;
    background: var(--board-sink);
    border-radius: 2px;
    box-shadow:
        inset 0 1px 2px rgba(23, 25, 27, 0.16),
        inset 0 0 0 1px rgba(23, 25, 27, 0.1);
    transition: box-shadow 0.35s var(--draw), transform 0.35s var(--draw);
}

.sample:hover,
.sample:focus-visible {
    transform: translateY(-2px);
    box-shadow:
        inset 0 0 0 1px rgba(23, 25, 27, 0.5),
        0 16px 32px -18px rgba(23, 25, 27, 0.5);
}

/* Pressed, a sample settles back into its recess — the one place on the
   board where a press has somewhere to go. These are the two largest
   targets on the page and the only route into either product, so they
   are the last things that should feel dead under a thumb. */
.sample:active {
    transform: translateY(0) scale(0.995);
    box-shadow:
        inset 0 1px 3px rgba(23, 25, 27, 0.3),
        inset 0 0 0 1px rgba(23, 25, 27, 0.42);
    transition-duration: var(--press);
}

/* The chip itself — the piece of material. Both cut to the same size,
   like real swatches, so the only difference you read is the material. */
.chip {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 1px;
    overflow: hidden;
    isolation: isolate;
    box-shadow: 0 1px 3px rgba(23, 25, 27, 0.4);
}

.sample-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 2px 10px;
    text-align: left;
}

/* The product's own mark, at the size a sample gets labelled. */
.sample-icon {
    width: 40px;
    height: 40px;
    flex: none;
    border-radius: 9px;
    box-shadow: 0 1px 3px rgba(23, 25, 27, 0.32);
}

.sample-foot .t-note { margin-left: auto; }

.sample-name {
    min-width: 0;
    font-variation-settings: 'wdth' 88;
    font-weight: 600;
    font-size: 1.14rem;
    letter-spacing: -0.015em;
}

.sample-name span {
    display: block;
    font-variation-settings: 'wdth' 100;
    font-weight: 400;
    font-size: 0.844rem;
    letter-spacing: 0;
    color: var(--ink-2);
    margin-top: 3px;
}

/* Chip 01 — Liquid Glass, assembled the way the material is: a field
   of the app's own content, a plate floating over it that bends what is
   behind, a rim, and a specular sweep. The blur is doing real work —
   the rows are legibly displaced under the plate. */
.chip-glass {
    background:
        radial-gradient(78% 82% at 22% 8%, #2f6dff 0%, transparent 62%),
        radial-gradient(74% 78% at 88% 96%, #8b46f0 0%, transparent 60%),
        linear-gradient(150deg, #16204f 0%, #241452 56%, #0b1132 100%);
}

.chip-glass .glass-field {
    position: absolute;
    inset: 12% 9% 36%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: transform 0.8s var(--draw);
}

.chip-glass .glass-row { display: flex; align-items: center; gap: 3.4%; }

.chip-glass .glass-row i {
    width: 4.2%;
    aspect-ratio: 1;
    flex: none;
    border-radius: 50%;
    border: 1.5px solid rgba(255, 255, 255, 0.62);
}

.chip-glass .glass-row b {
    height: 5.4%;
    min-height: 4px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.62);
}

.chip-glass .glass-row:nth-child(even) b { background: rgba(255, 255, 255, 0.4); }
.chip-glass .glass-row:nth-child(even) i { border-color: rgba(255, 255, 255, 0.42); }

.sample:hover .chip-glass .glass-field { transform: translateY(-3%); }

/* The plate. Backdrop blur is the effect being quoted, not a frost. */
.chip-glass .glass-plate {
    position: absolute;
    /* Clear of the list. A floating toolbar overlapping content is what the
       app does, but a row cut in half by it just reads as a mistake. */
    left: 14%;
    right: 14%;
    bottom: 8%;
    height: 15.5%;
    min-height: 28px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.1);
    -webkit-backdrop-filter: blur(9px) saturate(180%) brightness(1.15);
    backdrop-filter: blur(9px) saturate(180%) brightness(1.15);
    box-shadow:
        0 8px 22px -8px rgba(0, 0, 0, 0.66),
        inset 0 1px 0 rgba(255, 255, 255, 0.62),
        inset 0 0 0 1px rgba(255, 255, 255, 0.24);
    display: flex;
    align-items: center;
    gap: 3%;
    padding: 0 4.5%;
    transition: transform 0.5s var(--draw);
}

.sample:hover .chip-glass .glass-plate { transform: translateY(-6%); }

.chip-glass .glass-dot {
    width: 10px;
    height: 10px;
    flex: none;
    border-radius: 50%;
    background: linear-gradient(135deg, #7ea8ff, #b98cff);
    box-shadow: 0 0 10px rgba(150, 180, 255, 0.7);
}

.chip-glass .glass-hint {
    flex: 1;
    min-width: 0;
    font-size: clamp(8px, 0.86vw, 11px);
    line-height: 1;
    color: rgba(255, 255, 255, 0.94);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chip-glass .glass-key {
    width: 12px;
    height: 12px;
    flex: none;
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.26);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);
}

/* The specular sweep that tells you it is glass and not a card. */
.chip-glass::after {
    content: '';
    position: absolute;
    inset: -20%;
    z-index: 3;
    pointer-events: none;
    background: linear-gradient(102deg, transparent 38%, rgba(255, 255, 255, 0.22) 50%, transparent 62%);
    transform: translateX(-46%);
    transition: transform 1.15s var(--draw);
}

.sample:hover .chip-glass::after { transform: translateX(46%); }

/* Chip 02 — true black. The material is the absence of the other
   chip: no colour, no gradient, one lit edge with the app's own
   profile standing in it. Drawn live by js/board.js. */
/* Chip 02 — true black. The material is the absence of the other chip:
   no colour, no gradient of its own, one lit display for the darkness to
   be dark against. Without that light the sample is an empty rectangle,
   which is exactly the trap the app itself sits in. */
.chip-black { background: #000; }

/* A display that is switched on, gathering its brightness toward the right
   so the edge has the most to be dark against. */
.chip-black .black-lit {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(78% 104% at 100% 52%, rgba(152, 178, 240, 0.66) 0%, rgba(106, 128, 196, 0.3) 48%, transparent 78%),
        radial-gradient(48% 40% at 88% 2%, rgba(166, 138, 232, 0.34), transparent 74%),
        radial-gradient(60% 52% at 86% 100%, rgba(80, 160, 212, 0.4), transparent 76%),
        linear-gradient(116deg, #0d1122 0%, #161c34 50%, #202949 100%);
    transition: opacity 0.6s var(--draw);
}

.sample:hover .chip-black .black-lit { opacity: 0.86; }

.chip-black canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* ── Dimension lines ───────────────────────────────────────── */

/* A real dimension: two witness lines, one measure between them,
   the figure sitting on the line. Used once per sample so the
   samples read as drawn objects rather than thumbnails. */
.dim-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 2px 12px;
    color: var(--ink-3);
}

.dim-line {
    flex: 1;
    height: 5px;
    position: relative;
    border-left: 1px solid var(--hair);
    border-right: 1px solid var(--hair);
}

.dim-line::before {
    content: '';
    position: absolute;
    inset: 50% 0 auto;
    height: 1px;
    background: var(--hair);
}

/* ── Product bands ─────────────────────────────────────────── */

/* One product per sheet, in the order they are mounted on the cover, so
   nothing swaps sides as you scroll. Centred on the sheet's own axis: the
   drawing is the widest thing on the page and everything else is measured
   against its middle, which is how a plate is laid out on a board. */
.band { text-align: center; }
/* On a plate the title is centred and its code sits under it. Beside it, the
   pair is what gets centred and the title itself never is. */
.band .sheet-head {
    display: block;
    text-align: center;
    padding-bottom: 16px;
}
.band .sheet-head .t-dim { margin-top: 9px; }

.band-say { max-width: 62ch; margin: 0 auto clamp(34px, 4.6vw, 60px); }

.band-claim {
    font-size: clamp(1.44rem, 2.6vw, 2.15rem);
    font-variation-settings: 'wdth' 90;
    font-weight: 600;
    line-height: 1.14;
    letter-spacing: -0.026em;
    margin-bottom: 16px;
    text-wrap: balance;
}

.band-say .t-body {
    font-size: 1.02rem;
    line-height: 1.62;
    max-width: 54ch;
    margin: 0 auto;
}

/* ── The drawings ──────────────────────────────────────────── */

/* Both are graphite on the board. The products' own materials are quoted on
   the samples and on their own pages; here the board is explaining, and a
   board explains in pencil. */
.band-fig { margin: 0 auto; max-width: 780px; }

/* The numbers close the plate, under the thing they measure. */
.band-foot { max-width: 860px; margin: 0 auto; }
.band-fig figcaption { margin-top: 16px; }
.profile { width: 100%; height: auto; display: block; }

/* A transcript, set as a drawn note rather than a chat window. */
.talk { max-width: 620px; margin: 0 auto; padding: 24px 0 26px; border-top: 1px solid var(--ink); }

.talk-q {
    font-size: clamp(1.1rem, 1.6vw, 1.3rem);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.3;
    margin-bottom: 14px;
}
.talk-q::before { content: '\201C'; }
.talk-q::after  { content: '\201D'; }

.talk-a { color: var(--ink-2); font-size: 1rem; line-height: 1.6; max-width: 46ch; margin: 0 auto; }

/* The measurement that makes the answer unusual. Red is the figure pencil,
   so the numbers are red and nothing is filled. */
.gauge {
    max-width: 620px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    border-top: 1px solid var(--hair);
}

.gauge-row { padding: 16px 8px 4px; }
.gauge dt { font-family: var(--mono); font-size: 0.688rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 8px; }
.gauge dd { font-size: 1.18rem; font-weight: 600; letter-spacing: -0.02em; }
.gauge dd.mark { color: var(--redline-ink); }

/* A specification list, read across rather than down: the same questions
   asked of every product, answered in one line each. */
.specs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0;
    margin: clamp(38px, 4.8vw, 62px) 0 clamp(24px, 2.6vw, 32px);
    border-top: 1px solid var(--ink);
}

.specs > div { padding: 16px 14px 0; }
.specs dd { text-wrap: balance; }

.specs dt {
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: 7px;
}

.specs dd { font-size: 0.938rem; line-height: 1.45; }

/* Drawn-line reveal: the ink arrives along the line's own length,
   which is how a line gets onto paper. */
.js .ink-line { stroke-dasharray: var(--len); stroke-dashoffset: var(--len); }
.drawn .ink-line { animation: ink 1.15s var(--draw) forwards; animation-delay: var(--d, 0s); }
@keyframes ink { to { stroke-dashoffset: 0; } }

.js .ink-fade { opacity: 0; }
.drawn .ink-fade { animation: inkfade 0.6s var(--draw) forwards; animation-delay: var(--d, 0s); }
@keyframes inkfade { to { opacity: 1; } }

/* Poché goes on after the outline is closed, which is the order a drawing is
   made in and the reason the hatch reads as fill rather than as texture. */
.js .poche { opacity: 0; }
.drawn .poche { animation: inkfade 0.75s var(--draw) forwards; animation-delay: calc(var(--d, 0s) + 0.85s); }

/* The specification row lands column by column, left to right. */
.js .specs > div { opacity: 0; transform: translateY(8px); }
.drawn-foot .specs > div {
    animation: liftin 0.7s var(--draw) forwards;
    animation-delay: calc(var(--i, 0) * 0.07s);
}
@keyframes liftin { to { opacity: 1; transform: none; } }

/* ── Schedule table ────────────────────────────────────────── */

/* The four kinds of work, as a drawing schedule. A schedule is a
   table because the columns are the same question asked of every
   row — which is exactly true here, and is not true of four cards. */
.schedule { width: 100%; border-collapse: collapse; }

.schedule th {
    font-family: var(--mono);
    font-size: 0.688rem;
    font-weight: 400;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--ink-3);
    text-align: left;
    padding: 0 20px 11px 0;
    border-bottom: 1px solid var(--ink);
    white-space: nowrap;
}

.schedule td { padding: 20px 20px 20px 0; border-bottom: 1px solid var(--hair); vertical-align: baseline; }
.schedule tr:last-child td { border-bottom: 1px solid var(--ink); }
.schedule tr { transition: background 0.24s; }
.schedule tbody tr:hover { background: rgba(23, 25, 27, 0.035); }

.schedule .col-mark { width: 1%; white-space: nowrap; }
.schedule .col-mark span {
    font-family: var(--mono);
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    color: var(--redline-ink);
}

.schedule .col-work { width: 21%; }
.schedule .col-work strong { font-weight: 600; font-size: 1.06rem; letter-spacing: -0.015em; }
.schedule .col-note { color: var(--ink-2); font-size: 0.938rem; line-height: 1.55; }
.schedule .col-form { color: var(--ink-3); font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.04em; white-space: nowrap; }

/* ── Title block ───────────────────────────────────────────── */

/* Every drawing ends in a title block: who drew it, what it is,
   at what scale, and how to reach them. So does this one. */
.block {
    border-top: 1px solid var(--ink);
    background: var(--board-sink);
}

.block-inner { max-width: var(--sheet); margin: 0 auto; padding: clamp(40px, 5vw, 68px) var(--gutter) 0; }

.block-grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr 1fr;
    border-left: 1px solid var(--hair);
    border-top: 1px solid var(--hair);
}

.block-cell {
    padding: 22px 20px 26px;
    border-right: 1px solid var(--hair);
    border-bottom: 1px solid var(--hair);
    min-height: 132px;
}

.block-cell dt {
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: 12px;
}

.block-cell dd { font-size: 0.938rem; line-height: 1.75; }
/* Inline-block with real vertical padding: a 16px link box is under the
   minimum target size however comfortable the line-height around it looks. */
.block-cell dd a { display: inline-block; padding: 4px 0; color: var(--ink-2); transition: color 0.2s; }
.block-cell dd a:hover { color: var(--redline-ink); }

.block-title {
    font-variation-settings: 'wdth' 78;
    font-weight: 700;
    font-size: clamp(1.8rem, 3.2vw, 2.5rem);
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 10px;
}

.block-foot {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 22px;
    justify-content: space-between;
    padding: 16px 0 26px;
}

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

.js .up {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.8s var(--draw), transform 0.8s var(--draw);
    /* Promoted only while the rise is still owed. Carrying the hint on every
       block for the life of the page is how a will-change turns from an
       optimisation into a memory bill. */
    will-change: opacity, transform;
}

.up.seen { opacity: 1; transform: none; will-change: auto; }
.up.d1 { transition-delay: 0.08s; }
.up.d2 { transition-delay: 0.16s; }
.up.d3 { transition-delay: 0.24s; }

/* ── Adaptation ────────────────────────────────────────────── */

@media (max-width: 1080px) {
    .block-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 900px) {
    /* The rule after the wordmark divided it from the sheet index; with the
       index gone it divides it from nothing. */
    .rail-mark { padding-right: 0; border-right: none; }
    .cover-head { grid-template-columns: 1fr; gap: 26px; align-items: start; }
    .cover { min-height: 0; padding-top: calc(var(--rail) + 54px); }
    .samples { grid-template-columns: 1fr; }
    .specs { grid-template-columns: 1fr 1fr; }
    .rail-nav { display: none; }
    /* Narrow, not gone: the column reappears as a line inside each stacked
       row at the next breakpoint down. */
    .schedule .col-form { display: none; }
    .schedule th.col-form { display: none; }
}

@media (max-width: 620px) {
    body { font-size: 1rem; }
    .block-grid { grid-template-columns: 1fr; }
    .block-cell { min-height: 0; }
    .schedule .col-work { width: auto; }
    .schedule thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .schedule td { display: block; padding: 0 0 6px; border: none; }
    .schedule tr { display: block; padding: 18px 0; border-bottom: 1px solid var(--hair); }
    .schedule tr:last-child { border-bottom: 1px solid var(--ink); }
    .schedule td:last-child { padding-bottom: 0; }
    .schedule .col-mark { width: auto; }
    .specs { grid-template-columns: 1fr; }
    .specs > div { padding: 14px 0 0; }
    .gauge { grid-template-columns: 1fr; }
    .gauge-row { padding: 14px 0 4px; border-bottom: 1px solid var(--hair); }
    /* Back in the stacked layout, where there is room for it. */
    .schedule .col-form { display: block; padding-top: 8px; }
    .rail-meta .rail-scale { display: none; }
}

/* Reduced motion means a gentler equivalent, not silence.
   ------------------------------------------------------------------
   Killing every transition outright also kills the colour and opacity
   changes that tell a reader something responded to them — the press
   state, the hover, the leader line. So movement is what is dropped:
   the transition list is narrowed to the properties that do not travel,
   which leaves transforms to apply instantly and keeps the cross-fade
   that carries the meaning. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .js .samples .sample { opacity: 1; filter: none; }
    .cover-actions::after { transform: scaleX(1); }
    .js .poche, .js .specs > div { opacity: 1; transform: none; }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-property: opacity, color, background-color, border-color, box-shadow, outline-color !important;
        transition-duration: 0.18s !important;
    }
    .js .up { opacity: 1; transform: none; }
    .js .ink-line { stroke-dashoffset: 0; }
    .js .ink-fade { opacity: 1; }
    /* The one moving part left, and the one that matters most: the press
       still registers, as weight instead of travel. */
    .sample:active { transform: none; }
    .btn:active { transform: none; }
}

/* Frostier, not transparent. The rail is the only translucent surface on
   the board; asked for less transparency it becomes the sheet it floats
   over, and the glass chip drops the blur it is quoting. */
@media (prefers-reduced-transparency: reduce) {
    .rail {
        background: var(--board);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    .chip-glass .glass-plate {
        background: rgba(38, 46, 96, 0.86);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
}

/* Near-solid grounds and a defined edge. The hairlines that separate the
   title block and the schedule are set at 0.11–0.22 alpha, which is a
   deliberate whisper and exactly what this setting asks to be told louder. */
@media (prefers-contrast: more) {
    :root {
        --ink-2:  #2a2d2c;
        --ink-3:  #333735;
        --hair:   rgba(23, 25, 27, 0.55);
        --hair-2: rgba(23, 25, 27, 0.34);
        --redline-ink: #8f1f11;
    }
    .rail {
        background: var(--board);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
        border-bottom: 1px solid var(--ink);
    }
    .btn-line { border-width: 2px; }
    .sample { box-shadow: inset 0 0 0 2px var(--ink); }
    :focus-visible { outline-width: 3px; }
}

/* The way back out of the preview. */
.back-live { display: inline-flex; align-items: center; min-height: 44px; color: var(--ink-2); transition: color 0.2s; }
.back-live:hover { color: var(--redline-ink); }
