/* vibes-css:begin — generated from vibes/defs/iron-age.js by tools-check/vibes-css.mjs. Do not edit between the markers: change the definition, then run it with --write. */
:root[data-vibe="iron-age"] {
  --photo-band-summary-hero: 80px;
  --shape-rule-ink: #1c1712;
  --shape-rule-hair: .5px;
  --shape-rule-head-0: 2px;
  --shape-rule-head-1: 1.5px;
  --shape-rule-head-2: .75px;
  --shape-rule-sub-0: .75px;
  --shape-rule-sub-1: 0;
  --shape-rule-sub-2: 0;
  --shape-rule-total-0: 1px;
  --shape-rule-total-1: 2px;
  --shape-rule-total-2: 1px;
  --shape-leader-ink: #565450;
  --shape-leader-dot: 1.5px;
  --shape-leader-pitch: 4.5px;
  --shape-leader-min: 16px;
  --shape-band-fill: #d2cab7;
  --shape-band-ink: #1c1712;
  --shape-band-height: 30px;
  --shape-gutter: 2px;
  --shape-keyline-ink: #1c1712;
  --shape-keyline-width: 1px;
  --shape-lead-keyline: 1;
  --shape-cue-ink: #1c1712;
  --shape-chosen-tick: 0;
  --shape-rank-column: 0;
  --rack: #e6dec9;
  --bar: #ebe4ce;
  --collar: #c4b79b;
  --knurl: #77736a;
  --chalk: #1c1712;
  --steel: #4a3f31;
  --dim: #565450;
  --p-red: #82180c;
  --p-blue: #1f4a72;
  --p-yellow: #8b6600;
  --p-green: #0e5f40;
  --p-white: #2a241d;
  --p-chrome: #6a6d6c;
  --good: #0e5f40;
  --warn: #6e4d08;
  --bad: #82180c;
  --ink-plate: #f6efdd;
  --accent: #a1374f;
  --focus: #a1374f;
  --accent-press: #8e3548;
  --ink: #f6efdd;
  --danger: #82180c;
  --on-danger: #f6efdd;
  --done: #0e5f40;
  --ink-go: #f6efdd;
  --well: #e6dec9;
  --knockout: #ebe4ce;
  --inverse: #1c1712;
  --cal-mark: #ffffff;
  --raised: #d2cab7;
  --track: #d6c8a8;
  --grip: #7b6c52;
  --faint: #565450;
  --band: #1c1712;
  --knob: #4a3f31;
  --greet-name: #a1374f;
  --tint-runway: rgba(230,222,201,.55);
  --tint-runway-edge: rgba(230,222,201,.7);
  --font: 'Archivo', system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, monospace;
  --font-display: 'iron-age Besley', 'Archivo', system-ui, -apple-system, sans-serif;
  --font-italic: 'Archivo', system-ui, -apple-system, sans-serif;
  --font-num: 'iron-age Besley Digits';
  --r: 0;
  --r-sm: 0;
  --r-sheet: 0;
  --r-tile: 0;
  --r-pill: 999px;
  --r-plate: 0;
  --r-chip: 0;
  --r-mark: 0;
  --r-idx: 0;
  --r-round: 50%;
  --r-hair: 0;
  --r-bubble: 0;
  --r-badge: 0;
  --shadow-peek: none;
  --shadow-rest: none;
  --shadow-toast: none;
  --shadow-fab: none;
  --shadow-fab-pressed: none;
  --shadow-tour-card: none;
  --shadow-cal-tick: 0 0 0 1px #1c1712;
  --shadow-flame: inset 0 0 0 1px rgba(161,55,79,.35);
  --shadow-kpi-day: inset 0 0 0 1.2px #77736a;
  --shadow-kpi-day-on: none;
  --shadow-kpi-today: 0 0 0 1.5px #e6dec9, 0 0 0 2.5px #1c1712;
  --shadow-kpi-today-on: 0 0 0 1.5px #e6dec9, 0 0 0 2.5px #1c1712;
  --shadow-guide-eaten: inset 0 0 0 1px #77736a;
  --shadow-traj-good: 0 0 0 4px rgba(14,95,64,.15);
  --shadow-traj-warn: 0 0 0 4px rgba(110,77,8,.15);
  --shadow-traj-bad: 0 0 0 4px rgba(130,24,12,.15);
  --shadow-tour-lit: 0 0 0 2px #a1374f;
  --shadow-cal-head: 0 0 0 1px #1c1712;
  --shadow-cal-target: 0 0 0 1px #1c1712;
  --blur-sheet: none;
  --blur-dock: none;
  --blur-wk-bar: none;
  --scrim-tour: linear-gradient(to bottom, rgba(28,23,18,.8) 0%, rgba(28,23,18,.8) 42%);
  --video-bg: #000000;
  --rack-rgb: 230,222,201;
  --shade-rgb: 28,23,18;
  --lift-rgb: 28,23,18;
  --accent-rgb: 161,55,79;
  --p-yellow-rgb: 139,102,0;
  --warn-rgb: 110,77,8;
  --p-red-rgb: 130,24,12;
  --bad-rgb: 130,24,12;
  --danger-rgb: 130,24,12;
  --p-blue-rgb: 31,74,114;
  --p-green-rgb: 14,95,64;
  --done-rgb: 14,95,64;
  --good-rgb: 14,95,64;
  --p-white-rgb: 42,36,29;
  --steel-rgb: 74,63,49;
  --tag-ink-w: #6e4d08;
  --tag-ink-f: #82180c;
  --tag-ink-d: #1f4a72;
  --ink-of-p-red: #82180c;
  --ink-of-p-blue: #1f4a72;
  --ink-of-p-yellow: #6e4d08;
  --ink-of-p-green: #0e5f40;
  --ink-of-p-white: #2a241d;
  --ink-of-p-chrome: #4a3f31;
}
:root[data-vibe="iron-age"]::before { content: ''; position: fixed; top: 0; left: 0; right: 0; height: var(--safe-top); background: var(--band); pointer-events: none; z-index: 400; }
/* vibes-css:end */

/* ==========================================================================
   Iron Age — the hand-written half. Ink on cream, circa 1900: a physical-
   culture manual printed about 1904. The spec, block by block, is
   ~/dev/vibes-night/design/iron-age.md (§7 the looks, §8 the screens); the
   looks are VOCAB.md's, drawn from the tokens above and the `shape` params
   (--shape-*), so the geometry lives in the definition and only the drawing
   lives here.

   THE RULES THIS FILE KEEPS
   - Every selector starts [data-vibe="iron-age"] (tools-check/vibes-scope.mjs).
     Rules for the Vibes sheet's own tile are [data-vibe="iron-age"].vibe-in,
     so they reach Iron Age's tile and no other, whichever vibe is worn.
   - Looks, never words. No rule here writes a character (every ::before and
     ::after is content ''), and no text is transformed except undone: v1's
     caps labels show as they were written (type.* upper: 0).
   - Weight is set only through font-variation-settings. The two faces are
     Besley v4, latin subsets, each keeping its wght axis (FONTS.json).
     Besley sets heads, card heads, the greeting and the challenge figure;
     Archivo, v1's, sets everything else — every value, delta, date line,
     button, chip, the dock and the Coach card. (The italic's file,
     iron-age-besley-italic.woff2, stays in the folder unused since the
     second AI-made panel.)
   - One !important, as V59 §5.9 allows: the Steps "to go" figure's size
     beats steps.js's inline 26, commented at the rule.
   - Rules are ink. Each is drawn as vector rules at the definition's widths
     (--shape-rule-*) with the ink-bleed strip (textures/rule-*.png, seed
     1912) laid over them, so a strip that has not loaded yet leaves the
     vector rule, never a gap (spec §11).
   ========================================================================== */

/* ---------- the faces (vibes/iron-age/fonts; OFL.txt and FONTS.json beside
   them). Family names are the vibe's. The weight ranges are descriptors, so
   a heavier request than a face holds is never synthesised. ---------- */
@font-face {
  font-family: 'iron-age Besley';
  src: url(iron-age/fonts/iron-age-besley.woff2) format('woff2');
  font-weight: 600 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'iron-age Besley Digits';
  src: url(iron-age/fonts/iron-age-besley-digits.woff2) format('woff2');
  font-weight: 600 800; font-style: normal; font-display: swap;
}

/* ---------- the page: book stock with the `manual` grain (seed 1897), on
   the page only — never a sheet, plate, field, the dock or a photo band ---------- */
:root[data-vibe="iron-age"],
:root[data-vibe="iron-age"] body,
[data-vibe="iron-age"] #auth,
[data-vibe="iron-age"] #gate,
[data-vibe="iron-age"] #onboard:not(.ob-tour) {
  background-color: var(--rack);
  background-image: url(iron-age/textures/grain-manual@3x.png);
  background-image: -webkit-image-set(url(iron-age/textures/grain-manual@2x.png) 2x, url(iron-age/textures/grain-manual@3x.png) 3x);
  background-size: 72px 72px;
  background-repeat: repeat;
}

/* ---------- type: the heads in Besley ---------- */
[data-vibe="iron-age"] h1,
[data-vibe="iron-age"] h2,
[data-vibe="iron-age"] h3 {
  font-family: var(--font-display);
  font-variation-settings: 'wght' 800;
  letter-spacing: 0;
  font-synthesis: none;
}
[data-vibe="iron-age"] h1 { font-size: 24px; line-height: 1.1; }
/* Besley's figures are proportional unless asked (FONTS.json): every run it
   sets — a head, a card head, the running meta — takes tabular lining
   figures, so a date or a total in a head never shifts width as it changes. */
[data-vibe="iron-age"] h1,
[data-vibe="iron-age"] h2,
[data-vibe="iron-age"] h3,
[data-vibe="iron-age"] .eyebrow,
[data-vibe="iron-age"] .chart-sub,
[data-vibe="iron-age"] .card-sub,
[data-vibe="iron-age"] .you-sub,
[data-vibe="iron-age"] .you-since,
[data-vibe="iron-age"] .summary-date,
[data-vibe="iron-age"] .ob-kicker,
[data-vibe="iron-age"] .you-sec-t,
[data-vibe="iron-age"] .you-greet,
[data-vibe="iron-age"] .ex-name,
[data-vibe="iron-age"] .wk-block-title,
[data-vibe="iron-age"] .day-title,
[data-vibe="iron-age"] .review-verdict {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
[data-vibe="iron-age"] h2 { font-size: 18px; line-height: 1.15; }

/* eyebrow · v1, its type role Besley SemiBold 15, sentence case, ink */
[data-vibe="iron-age"] .eyebrow,
[data-vibe="iron-age"] .chart-sub {
  font-family: var(--font-display);
  font-size: 15px; line-height: 1.2;
  letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wght' 600;
  font-synthesis: none;
}
/* The running head (type.statLbl): the masthead's kicker, the recap's, a
   sheet's and onboarding's — Archivo 12/600 in steel, roman, as written. A
   page's running head is small type, not a second display face: no screen
   stacks an italic kicker over its title (the first AI-made panel); the
   masthead's sits at the end of the head rule the title hangs from (below). */
[data-vibe="iron-age"] .cal-hd .eyebrow,
[data-vibe="iron-age"] .summary-hero .eyebrow,
[data-vibe="iron-age"] .sheet .eyebrow:has(+ h2),
[data-vibe="iron-age"] .ob-kicker {
  font-family: var(--font);
  font-size: 12px; line-height: 1.3;
  letter-spacing: 0; text-transform: none;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
/* The running meta (type.meta): Archivo 13, roman, steel — a card's "last 7
   days", the greeting's date, "Member since …", the recap's date. An italic
   serif date line under a serif head read as a machine's signature (the
   second AI-made panel); the period set its dates in the text's roman. */
[data-vibe="iron-age"] .card-sub,
[data-vibe="iron-age"] .you-sub,
[data-vibe="iron-age"] .you-since,
[data-vibe="iron-age"] .summary-date {
  font-family: var(--font);
  font-size: 13px; line-height: 1.35;
  letter-spacing: 0; text-transform: none;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 400;
}
/* A figure's unit, on its baseline in Archivo 13 steel as written
   ("kcal left today", "to go", "ml of 2,500 ml") — Besley never sets a unit. */
[data-vibe="iron-age"] .fuel-top .eyebrow,
[data-vibe="iron-age"] .st-hero-side .eyebrow,
[data-vibe="iron-age"] .water-right .eyebrow,
[data-vibe="iron-age"] .load-num + .eyebrow {
  font-family: var(--font);
  font-size: 13px; line-height: 1.3;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}

/* The challenge figure (headline · rule, loadNum): Besley ExtraBold, tabular
   lining figures, at each site's own size. */
[data-vibe="iron-age"] .load-num,
[data-vibe="iron-age"] .headline-v {
  font-family: var(--font-display);
  font-variation-settings: 'wght' 800;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  letter-spacing: 0; line-height: 1;
  font-synthesis: none;
}
[data-vibe="iron-age"] .headline-v { font-size: 28px; }

/* Archivo's figures at its own width: v1 stamps them wide (108–118); a
   manual's table sets them at the text's. */
[data-vibe="iron-age"] .stat-val,
[data-vibe="iron-age"] .kpi-val,
[data-vibe="iron-age"] .fe-cal,
[data-vibe="iron-age"] .pb-val,
[data-vibe="iron-age"] .rank-val,
[data-vibe="iron-age"] .sess-e1,
[data-vibe="iron-age"] .pr-val,
[data-vibe="iron-age"] .mini-stat-v,
[data-vibe="iron-age"] .adm-n,
[data-vibe="iron-age"] .ob-num-v,
[data-vibe="iron-age"] .thesis-line b,
[data-vibe="iron-age"] .donut-top,
[data-vibe="iron-age"] .ring-top,
[data-vibe="iron-age"] .st-ring-n,
[data-vibe="iron-age"] .review-take-t {
  font-variation-settings: 'wdth' 100, 'wght' 800;
  letter-spacing: 0;
}
[data-vibe="iron-age"] .review-take-t { font-variation-settings: 'wdth' 100, 'wght' 400; }

/* v1's small caps labels, as written, at 11–12 (nothing new under 11). */
[data-vibe="iron-age"] .stat-lbl,
[data-vibe="iron-age"] .kpi-lbl,
[data-vibe="iron-age"] .field label,
[data-vibe="iron-age"] .field-lbl,
[data-vibe="iron-age"] .mini-stat-l,
[data-vibe="iron-age"] .ring-lbl,
[data-vibe="iron-age"] .sess-e1lbl {
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .field label .opt { letter-spacing: 0; color: var(--dim); }
[data-vibe="iron-age"] .field-hint { font-size: 12px; }
[data-vibe="iron-age"] .kpi-unit,
[data-vibe="iron-age"] .headline-u {
  font-size: 13px; letter-spacing: 0; text-transform: none; color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .headline-u { margin-left: -6px; }
[data-vibe="iron-age"] .kpi-prev { font-size: 12px; letter-spacing: 0; color: var(--steel); }
[data-vibe="iron-age"] .card-sub,
[data-vibe="iron-age"] .fe-sub,
[data-vibe="iron-age"] .pr-sub,
[data-vibe="iron-age"] .pb-sub,
[data-vibe="iron-age"] .rank-sub,
[data-vibe="iron-age"] .sess-sub,
[data-vibe="iron-age"] .set-row-sub,
[data-vibe="iron-age"] .coach-build-w,
[data-vibe="iron-age"] .person-sub,
[data-vibe="iron-age"] .rt-meta,
[data-vibe="iron-age"] .rt-pv-sets,
[data-vibe="iron-age"] .day-ex-sets,
[data-vibe="iron-age"] .feel-sub { font-size: 12px; }
[data-vibe="iron-age"] .card-sub { font-size: 13px; }
[data-vibe="iron-age"] .ex-item .eq,
[data-vibe="iron-age"] .legend-item,
[data-vibe="iron-age"] .vol-name,
[data-vibe="iron-age"] .vol-val,
[data-vibe="iron-age"] .macro-pct,
[data-vibe="iron-age"] .cal-status,
[data-vibe="iron-age"] .cal-status .cal-maint,
[data-vibe="iron-age"] .traj-ends,
[data-vibe="iron-age"] .chart-foot,
[data-vibe="iron-age"] .ring-of,
[data-vibe="iron-age"] .st-src {
  font-size: 12px; letter-spacing: 0; text-transform: none;
}
[data-vibe="iron-age"] .legend-val { font-size: 11px; }
[data-vibe="iron-age"] .ai-cost,
[data-vibe="iron-age"] .cal-legend-item,
[data-vibe="iron-age"] .gate-sep,
[data-vibe="iron-age"] .swipe-hint {
  font-size: 11px; letter-spacing: 0; text-transform: none;
}
[data-vibe="iron-age"] .gate-sep { color: var(--steel); }
[data-vibe="iron-age"] .sync-pip {
  font-size: 11px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
/* The pip's mark is a printer's square in ink, not a green lamp: the word
   beside it says the state, and the mark tells it by shape as well — solid
   when synced, an open square in warn when not. A coloured dot with no key
   read as decoration (the third AI-made panel). */
[data-vibe="iron-age"] .sync-pip i { border-radius: 0; background: var(--chalk); }
[data-vibe="iron-age"] .sync-pip.off i { background: none; box-shadow: inset 0 0 0 1.5px var(--warn); }
/* The calorie line's mark: square, the key to the meter's eaten bar it
   takes its colour from (food.js sets both), not a status dot. */
[data-vibe="iron-age"] .cal-status i { border-radius: 0; }
[data-vibe="iron-age"] .note {
  font-size: 13px; line-height: 1.5; color: var(--dim);
}

/* ---------- the rules ----------
   Every head HANGS from its rule (shape.rule.place 'above'): the rule, then
   the words; nothing is underlined. Head (shape.rule.head [2]): the one a
   tab's title hangs from, and a sheet's top edge. Sub (shape.rule.sub
   [1.2]): an article's — a card head; the challenge figure and an
   exercise's name keep theirs under them. Total (shape.rule.total
   [1, 2, 1]): over the recap's totals and the estimate's, and round a
   lifting block. Hair (shape.rule.hair .5): rows, cells, columns. */

/* screenHeader · masthead ('above'): the page's running head — the words
   small and roman (statLbl) over a hairline across the title's column, as a
   book sets the head of its page — and the h1 in Besley ExtraBold standing
   clear under it on space, with no rule of its own. A label at the end of a
   heavy rule, over every title, read as the eyebrow-over-H1 template (the
   second and third AI-made panels). The column grows to the nav buttons,
   which keep their place and their 34. */
[data-vibe="iron-age"] .cal-hd {
  align-items: flex-end;
  margin-bottom: 16px;
}
[data-vibe="iron-age"] .cal-hd > div:first-child { flex: 1 1 auto; min-width: 0; }
[data-vibe="iron-age"] .cal-hd .eyebrow,
[data-vibe="iron-age"] .summary-hero .eyebrow {
  display: block;
  padding-bottom: 5px;
  margin-bottom: 14px;
  border-bottom: var(--shape-rule-hair) solid var(--shape-rule-ink);
}
/* The month, day and gear buttons are bare cuts, as a page's ‹ › are: no
   plate round them (one keyline box round every control read as a template,
   the first AI-made panel). Their 34 and their place are v1's; pressed, a
   leaf of raised paper shows the target. */
[data-vibe="iron-age"] .cal-nav button {
  background: none;
  border-color: transparent;
  color: var(--chalk);
}
[data-vibe="iron-age"] .cal-nav button:active { background: var(--raised); }
[data-vibe="iron-age"] .cal-nav button .glyph { width: 18px; height: 18px; }
/* The gear is a solid cut (vibes/icons/iron-age.js `cut`): no stroke. */
[data-vibe="iron-age"] .cal-nav .gear-btn svg { stroke-width: 0; }

/* sectionHeader · rule: the section head, h3 (Besley ExtraBold 18), hung
   from the Oxford rule (shape.rule.head, thick and thin) at full width —
   the chapter's rule, the heaviest on the page, over the heaviest head. An
   article under it hangs from the light rule (card-hd, below) and inside an
   article there is space alone: three ranks, where every head had the one
   rule (the third AI-made panel). 44 above, 12 below; no trailing hairline. */
[data-vibe="iron-age"] .you-sec { margin-top: 44px; }
[data-vibe="iron-age"] .you-sec-t {
  display: block; position: relative;
  margin-bottom: 12px;
  padding-top: calc(var(--shape-rule-head-0) + var(--shape-rule-head-1) + var(--shape-rule-head-2) + 9px);
  font-family: var(--font-display);
  font-size: 18px; line-height: 1.2;
  letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wght' 800;
  font-synthesis: none;
}
[data-vibe="iron-age"] .you-sec-t::after { display: none; }
[data-vibe="iron-age"] .you-sec-t::before {
  content: '';
  position: absolute; left: 0; right: 0; top: 0;
  height: calc(var(--shape-rule-head-0) + var(--shape-rule-head-1) + var(--shape-rule-head-2));
  /* read from the head outward (native looks.jsx Rule): the thick line
     against the words, the thin one above it */
  background:
    -webkit-image-set(url(iron-age/textures/rule-sub@2x.png) 2x, url(iron-age/textures/rule-sub@3x.png) 3x) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1) - 1px) / 144px 3px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-head-2) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1)) / 100% var(--shape-rule-head-0) no-repeat;
}

/* card · ruled (and youCard · ruled): no ground, no box, no corner. The head
   row hangs from the light article rule at full width (rule.sub .75,
   rule.place 'above'), 6 under it, the content 8 under the head and running
   to the rule's width; cards part by 20 — tight inside, the space between.
   The light rule carries no ink-bleed strip: the strip is the heavy rules'
   (the Oxford rule, the double rule over a total). */
[data-vibe="iron-age"] .card {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  margin-bottom: 20px;
}
[data-vibe="iron-age"] .card-hd {
  position: relative;
  padding-top: calc(6px + var(--shape-rule-sub-0));
  margin-bottom: 8px;
}
[data-vibe="iron-age"] .card-hd::after {
  content: '';
  position: absolute; left: 0; right: 0; top: 0;
  height: var(--shape-rule-sub-0);
  background: var(--shape-rule-ink);
}
/* The challenge figure and an exercise's name keep their rule under them:
   a figure over its rule, a table under its title. */
[data-vibe="iron-age"] .ex-hd::after,
[data-vibe="iron-age"] .headline::after,
[data-vibe="iron-age"] .fuel-top::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--shape-rule-sub-0);
  background: var(--shape-rule-ink);
}
/* "Doing well" on a viridian rule, "Could improve" on an amber one, in place
   of v1's side stripes; which is which stays in the title words. */
[data-vibe="iron-age"] .card-wins,
[data-vibe="iron-age"] .card-improve { border-left: 0; }
[data-vibe="iron-age"] .card-wins .card-hd::after { background: var(--good); }
[data-vibe="iron-age"] .card-improve .card-hd::after { background: var(--warn); }
[data-vibe="iron-age"] .you-pair { gap: 16px; }
[data-vibe="iron-age"] .you-pair .card { padding: 0; }
[data-vibe="iron-age"] .meal-blank { padding-bottom: 0; }
[data-vibe="iron-age"] .meal-kcal { font-size: 13px; color: var(--steel); }
[data-vibe="iron-age"] .meal-blank .meal-kcal { font-size: 13px; letter-spacing: 0; text-transform: none; color: var(--dim); }
[data-vibe="iron-age"] .pr-card,
[data-vibe="iron-age"] .install-card { background: none; border-color: transparent; }

/* The lead plate: the boxed lead — Fuel's summary and the recap's
   certificate. Bar paper in a 1pt ink keyline (shape.lead.keyline), square,
   padding 20. The only thing in the vibe with both a fill and a border. */
[data-vibe="iron-age"] .card.fuel-sum,
[data-vibe="iron-age"] .summary-hero {
  position: relative;
  background: var(--bar);
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
  padding: 20px;
  margin-bottom: 20px;
}
/* The open lead: Steps' today and Weight's log carry no photo in this vibe,
   so they are not boxed (card · ruled). Each stands on the page straight
   under the tab's title — no ground, no sides, no rule of its own (a rule
   under a title that already hangs from one would box the title in): the
   one box on those tabs is Weight's field, the one it holds. */
[data-vibe="iron-age"] #view-steps .cal-hd + .card,
[data-vibe="iron-age"] #view-weight .cal-hd + .card { margin-bottom: 20px; }
/* BAND MODE (images.<slot>.band): the plate's halftone in a strip 80 tall
   across the top of its box, the box's padding grown by as much, so no word,
   control or colour sits on the photograph. Cover-cropped round the centre
   (the files are cut round their subjects: focal .5 / .5); the face rule was
   measured for exactly this crop at every box width. One plate only, a man
   at exercise: the recap's. No photo on You, Fuel, Steps, Weight, the Coach
   card or Start workout. */
[data-vibe="iron-age"] .summary-hero { padding-top: calc(20px + var(--photo-band-summary-hero)); }
[data-vibe="iron-age"] .summary-hero::before {
  content: '';
  position: absolute; left: 0; right: 0; top: 0;
  height: var(--photo-band-summary-hero);
  background: url(iron-age/img/recap.png) center / cover no-repeat;
  border-bottom: var(--shape-keyline-width) solid var(--shape-keyline-ink);
}

/* ---------- youHero · banner ----------
   The greeting is not boxed and carries no photo (the vibe prints its one
   plate on the recap). In v1's order: the account's initials stamped in a
   square 1pt ink keyline at v1's 52 — the button it is, not a drop cap
   (Besley ExtraBold 22, ink; a profile photo is cut square inside it) — the
   greeting and the name in Besley ExtraBold 25, all one ink, and the gear as
   a bare cut. Both keep v1's targets (52 and 36). The date in the meta. */
[data-vibe="iron-age"] .you-avatar {
  background: none; color: var(--chalk);
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
  font-family: var(--font-display);
  font-size: 22px; line-height: 1;
  font-variation-settings: 'wght' 800;
  font-synthesis: none;
}
[data-vibe="iron-age"] .you-greet {
  font-family: var(--font-display);
  font-size: 25px; line-height: 1.08; letter-spacing: 0;
  font-variation-settings: 'wght' 800;
  font-synthesis: none;
}/* The name keeps v1's ellipsis for a long name, so its box clips: Besley's
   ink runs taller than its 27px line (34), so the clip box is grown by 4
   above and 8 below (and handed back as margin), and no ascender or
   descender is cut. */
[data-vibe="iron-age"] .you-greet-name { color: var(--chalk); padding: 4px 0 8px; margin: -4px 0 -8px; }
/* The date wraps rather than ending in an ellipsis: at 320 "Wednesday,
   September 30" can be wider than the room beside the avatar and the gear,
   and a date cut short is a changed word. */
[data-vibe="iron-age"] .you-hero .you-sub { margin-top: 6px; white-space: normal; overflow: visible; text-overflow: clip; }
[data-vibe="iron-age"] .you-gear {
  background: none;
  border-color: transparent;
  border-radius: 0;
  color: var(--chalk);
}
[data-vibe="iron-age"] .you-gear svg { width: 20px; height: 20px; stroke-width: 0; }
[data-vibe="iron-age"] .you-gear:active { background: var(--raised); }
[data-vibe="iron-age"] .you-since { margin: 10px 0 16px; }

/* the recap's hero: the masthead inside its plate — the running head, the
   head rule, the headline hanging from it */
[data-vibe="iron-age"] .summary-hero h1 { margin-top: 0; margin-bottom: 8px; }
[data-vibe="iron-age"] .summary-line { font-size: 15px; }
[data-vibe="iron-age"] .summary-date { margin-top: 6px; }

/* ---------- coachCard · ruled ----------
   Skin only. No ground; only the top and bottom of its 1pt border, in ink;
   square. The height (190 / 164), the padding, the border's width, the face
   and every line's clamp are v1's — cardLayout()'s — so the copy fits
   exactly as it does in v1. The balloon, COACH, COACH ME and the chevron are
   the rubric, the screen's one red. */
[data-vibe="iron-age"] .coach-card,
[data-vibe="iron-age"] .coach-card:active {
  background: none;
  border-color: var(--shape-rule-ink) transparent;
  border-radius: 0;
}
[data-vibe="iron-age"] .coach-go { border-top-color: var(--shape-rule-ink); }
/* COACH and COACH ME stay in the capitals they show in v1, at v1's size and
   face, but untracked — a word, not a letterspaced label (the second
   AI-made panel; v1 tracks them .16 / .14) — and in ink: the rubric is the
   balloon and the chevron. Tighter tracking only gives the question beside
   COACH ME more room. */
[data-vibe="iron-age"] .coach-ttl,
[data-vibe="iron-age"] .coach-go-t { letter-spacing: 0; color: var(--chalk); }
[data-vibe="iron-age"] .coach-go-x .glyph { width: 15px; height: 15px; vertical-align: -2px; }

/* ---------- sheetHost · full, sheetTitle · rule ---------- */
[data-vibe="iron-age"] .sheet-backdrop { background: rgba(var(--shade-rgb), .45); }
[data-vibe="iron-age"] .sheet {
  border-radius: 0;
  border-top: 0;
  padding-top: calc(10px + var(--shape-rule-head-0) + var(--shape-rule-head-1) + var(--shape-rule-head-2));
  /* the thin line on the sheet's edge, the thick one inward (native
     Sheet.jsx: the head rule read outward, up) */
  background:
    -webkit-image-set(url(iron-age/textures/rule-sub@2x.png) 2x, url(iron-age/textures/rule-sub@3x.png) 3x) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1) - 1px) / 144px 3px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-head-2) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1)) / 100% var(--shape-rule-head-0) no-repeat,
    var(--bar);
}
[data-vibe="iron-age"] .sheet-grab { border-radius: 0; }
/* sheetTitle · v1: the title in Besley with no rule under it — the sheet's
   top edge is its one rule. */
[data-vibe="iron-age"] .sheet .eyebrow:has(+ h2) { margin-bottom: 2px; }

/* ---------- statRow · runin ----------
   The stat rows were the ledger (a drawn leader on every stat line) until the
   second AI-made panel, then a box-score line between hairlines until the
   third: three equal columns of big figure over small label, on three tabs,
   is the stat-banner whatever draws its box.

   statRow · runin: the figures run in, as a manual sets them in its text —
   each value (Archivo 18/700, tabular, in the caller's colour) with its label
   after it on the same baseline (12/600 steel, as written), the stats in v1's
   order one after another, 18 apart, wrapping as a line of text wraps. No
   columns, no rules, no ground. A value never truncates; a long label wraps. */
[data-vibe="iron-age"] .stat-row,
[data-vibe="iron-age"] .mini-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  padding: 0;
  border: 0;
  background: none;
}
[data-vibe="iron-age"] .stat,
[data-vibe="iron-age"] .mini-stat {
  display: flex;
  align-items: baseline;
  gap: 5px;
  flex: 0 1 auto;
  min-width: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}
/* A value never ends in an ellipsis — a figure cut short is a changed
   number. */
[data-vibe="iron-age"] .stat-val,
[data-vibe="iron-age"] .mini-stat-v { display: block; flex: none; white-space: nowrap; line-height: 1.2; overflow: visible; text-overflow: clip; }
[data-vibe="iron-age"] .stat-val { font-size: 18px; font-variation-settings: 'wdth' 100, 'wght' 700; }
/* A run-in figure is small text (18/700), so a graphic-only plate is inked
   through inkOf: ochre as warn (5.74:1, 5.42 on the grain, where ochre is
   3.92) and pewter as steel. The callers set the colour inline
   (stats.js statRow: 'Best e1RM', 'var(--p-yellow)'); redefining the plate on
   the value itself re-inks that var() without !important. */
[data-vibe="iron-age"] .stat-val {
  --p-yellow: var(--ink-of-p-yellow);
  --p-chrome: var(--ink-of-p-chrome);
}
[data-vibe="iron-age"] .stat-lbl,
[data-vibe="iron-age"] .mini-stat-l { display: block; margin: 0; min-width: 0; white-space: normal; overflow: visible; text-overflow: clip; }
/* An article after a run-in line stands 20 clear of it, as cards part. */
[data-vibe="iron-age"] .stat-row + .card,
[data-vibe="iron-age"] .mini-stats + .card,
[data-vibe="iron-age"] .note + .card { margin-top: 20px; }
[data-vibe="iron-age"] .stat-row { margin-top: 4px; margin-bottom: 14px; }
[data-vibe="iron-age"] .mini-stats { margin-top: 10px; }
[data-vibe="iron-age"] .mini-stat-v { font-size: 16px; }
/* The recap's session totals: the run-in line under the double rule
   (shape.rule.total), the form's totals. */
[data-vibe="iron-age"] .summary-page > .stat-row {
  padding-top: calc(var(--shape-rule-total-0) + var(--shape-rule-total-1) + var(--shape-rule-total-2) + 9px);
  margin-bottom: 24px;
  background:
    -webkit-image-set(url(iron-age/textures/rule-total@2x.png) 2x, url(iron-age/textures/rule-total@3x.png) 3x) 0 -1px / 144px 6px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-total-0) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-total-0) + var(--shape-rule-total-1)) / 100% var(--shape-rule-total-2) no-repeat;
}

/* ---------- kpi · word ----------
   No tile, no corner tint, no top band. The label with the delta in its pill
   at the right (the copy names the pill, you.js:802): the one rounded, tinted
   thing in the vibe, at tint.pill* — .06 ink, .10 of good, bad or warn. The
   22pt value, "last week …" in steel, a word-sized sparkline, the seven round
   day dots, today ringed in ink. The 2 × 2 grid and its order kept. */
[data-vibe="iron-age"] .kpi-grid { gap: 22px 18px; }
[data-vibe="iron-age"] .kpi {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}
[data-vibe="iron-age"] .kpi-val { font-size: 22px; margin-top: 7px; }
[data-vibe="iron-age"] .delta-pill { background: rgba(var(--lift-rgb), .06); }
[data-vibe="iron-age"] .delta-pill.up { background: rgba(var(--good-rgb), .10); }
[data-vibe="iron-age"] .delta-pill.down { background: rgba(var(--bad-rgb), .10); }
[data-vibe="iron-age"] .delta-pill.warn { background: rgba(var(--warn-rgb), .10); }
[data-vibe="iron-age"] .delta-pill .delta-v { font-size: 12px; }
[data-vibe="iron-age"] .delta-pill .delta-a { font-size: 11px; }
[data-vibe="iron-age"] .delta-v,
[data-vibe="iron-age"] .delta-a { font-variation-settings: 'wdth' 100, 'wght' 800; }
[data-vibe="iron-age"] .delta-l { font-size: 12px; letter-spacing: 0; }
[data-vibe="iron-age"] .kpi .chart-spark { width: 72px; margin-top: 8px; }
[data-vibe="iron-age"] .kpi-days { margin-top: 9px; }

/* ---------- headline · rule: the challenge line ----------
   The figure in Besley, its unit on the same baseline in Archivo, the single
   rule under it. At most one figure of 32 or more a screen. */
[data-vibe="iron-age"] .headline { position: relative; padding-bottom: 10px; margin-bottom: 4px; }
[data-vibe="iron-age"] .fuel-top { position: relative; padding-bottom: 12px; margin-bottom: 16px; padding-right: 30px; }

/* ---------- chip · stamp, segmented · boxes ----------
   One letterpress device for every choice on every screen: the words in an
   ink keyline (shape.keyline), square, no ground; the chosen one printed
   solid, ink with the words knocked out. Grey slugs for the chips beside an
   underline for the range pickers read as two stock components restyled
   (the third AI-made panel). */
[data-vibe="iron-age"] .chip,
[data-vibe="iron-age"] .move-opt,
[data-vibe="iron-age"] .coach-goal-opt {
  border-radius: 0;
  background: none;
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  color: var(--chalk);
  font-size: 12px;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .chip:active,
[data-vibe="iron-age"] .move-opt:active,
[data-vibe="iron-age"] .coach-goal-opt:active { background: var(--raised); }
[data-vibe="iron-age"] .chip.on,
[data-vibe="iron-age"] .move-opt.on,
[data-vibe="iron-age"] .coach-goal-opt.on,
[data-vibe="iron-age"] .coach-effort.on {
  background: var(--inverse);
  border-color: var(--inverse);
  color: var(--knockout);
}
/* Coach's questions are lines of type to press, not buttons: ink words
   under a 1pt rule, no box, each keeping v1's target. */
[data-vibe="iron-age"] .coach-chip {
  border-radius: 0;
  background: none;
  border-color: transparent;
  color: var(--chalk);
  font-size: 13px;
  font-variation-settings: 'wdth' 100, 'wght' 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  padding-left: 0; padding-right: 12px;
}
[data-vibe="iron-age"] .coach-chip:active { border-color: transparent; background: rgba(var(--lift-rgb), .04); }
[data-vibe="iron-age"] .coach-effort.on { padding-left: 12px; text-decoration: none; }
/* "How did that feel?": the ten energy figures and the five strengths are a
   printed form's blanks, not a grid of boxes — each figure over its own
   length of rule (1pt, ink), the row one ruled line. Chosen: the figure
   knocked out of an ink block standing on the rule. (The tick at each
   blank's left end is gone: at fractional widths two of ten drew heavier
   than the rest — the third AI-made panel.) */
[data-vibe="iron-age"] .feel-grid + .feel-cap { margin-top: 14px; }
[data-vibe="iron-age"] .feel-grid .coach-chip,
[data-vibe="iron-age"] .feel-steps .coach-chip {
  position: relative;
  min-height: 44px;
  margin: 0;
  padding: 6px 12px;
  border: 0;
  text-decoration: none;
  text-align: center;
  box-shadow: inset 0 -1px 0 var(--shape-rule-ink);
  font-size: 13px; line-height: 1.2;
  font-variation-settings: 'wdth' 100, 'wght' 700;
  font-feature-settings: 'tnum' 1;
}
[data-vibe="iron-age"] .feel-grid .coach-chip { padding-left: 0; padding-right: 0; }
/* The five strengths fill one line, the long one given its share, rather
   than wrapping four and one: the blanks a form has, all on one rule. */
[data-vibe="iron-age"] .feel-steps { display: grid; grid-template-columns: minmax(0, 1.9fr) repeat(4, minmax(0, 1fr)); gap: 8px; }
[data-vibe="iron-age"] .feel-steps .coach-chip { padding-left: 0; padding-right: 0; }
[data-vibe="iron-age"] .feel-grid .coach-chip.on,
[data-vibe="iron-age"] .feel-steps .coach-chip.on {
  background: var(--inverse);
  color: var(--knockout);
  border-color: transparent;
}
/* The segmented controls (segmented · boxes): the same device joined — the
   options in one ink keyline, square, parted by the keyline's own rule; the
   chosen cell printed solid with its words knocked out, the others ink on
   the paper. v1's height, equal widths. */
[data-vibe="iron-age"] .seg {
  gap: 0; padding: 0;
  background: none;
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .seg-btn {
  min-height: 36px;
  border-radius: 0;
  background: none;
  color: var(--chalk);
  font-size: 12px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .seg-btn + .seg-btn { border-left: var(--shape-keyline-width) solid var(--shape-keyline-ink); }
[data-vibe="iron-age"] .seg-btn.on {
  background: var(--inverse);
  color: var(--knockout);
  box-shadow: none;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}

/* ---------- btn · inverse ----------
   Primary: a solid ink block, knocked-out words, square. Plain: raised
   paper. Ghost: no box — steel words underlined 1pt, the 44 kept. Danger: a
   square 1.5pt Indian-red keyline. Start workout is a clean ink block. */
[data-vibe="iron-age"] .btn {
  border-radius: 0;
  font-variation-settings: 'wdth' 100, 'wght' 700;
  letter-spacing: .01em;
}
[data-vibe="iron-age"] .btn-primary { background: var(--inverse); color: var(--knockout); }
[data-vibe="iron-age"] .btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--steel);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
[data-vibe="iron-age"] .btn-ghost:active { color: var(--chalk); }
/* A ghost that holds only a drawn glyph (− + ⋯) has no word to underline:
   it is a square keyline plate at its v1 size. */
[data-vibe="iron-age"] .btn-ghost:has(> .glyph:only-child),
[data-vibe="iron-age"] .qty-row .btn-ghost {
  border-color: var(--shape-keyline-ink);
  color: var(--chalk);
}
[data-vibe="iron-age"] .btn-ghost .glyph { width: 18px; height: 18px; }
[data-vibe="iron-age"] .btn-danger { border-width: 1.5px; border-color: var(--danger); }
[data-vibe="iron-age"] .btn-lg { font-size: 16px; letter-spacing: .01em; text-transform: none; }
[data-vibe="iron-age"] .linkish {
  color: var(--steel);
  text-decoration-color: var(--steel);
}
[data-vibe="iron-age"] .back-btn { font-size: 13px; letter-spacing: 0; font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .back-btn .glyph { width: 15px; height: 15px; }
/* A count is a plain figure, tabular, in steel — as the Settings rows set
   theirs — not a stamped box. */
[data-vibe="iron-age"] .cnt,
[data-vibe="iron-age"] .add-secondary .cnt {
  border-radius: 0;
  border-color: transparent;
  background: none;
  color: var(--steel);
  font-size: 13px;
  font-variation-settings: 'wdth' 100, 'wght' 700;
  font-feature-settings: 'tnum' 1;
  text-decoration: none;
}
[data-vibe="iron-age"] .badge { border-radius: 0; background: var(--inverse); color: var(--knockout); }
/* Foods and Meals hold a cut, a word and a count: the word is underlined,
   the count stays a stamp, never a struck-through figure. */
[data-vibe="iron-age"] .add-secondary .btn-ghost { text-decoration: none; }
[data-vibe="iron-age"] .add-secondary .btn-ghost > span:not(.cnt) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

/* ---------- field · square ----------
   Bar ground, square, a 1pt knurl keyline (3:1 on bar); focus turns it
   madder. It stays a box: the copy says "this box" (food.js:3320). */
[data-vibe="iron-age"] .field input,
[data-vibe="iron-age"] .field select,
[data-vibe="iron-age"] .field textarea,
[data-vibe="iron-age"] .qty-row input,
[data-vibe="iron-age"] .picker-search input,
[data-vibe="iron-age"] .paste-box,
[data-vibe="iron-age"] .wpe-row input {
  background: var(--bar);
  border-color: var(--knurl);
  border-radius: 0;
}
[data-vibe="iron-age"] .field input:focus,
[data-vibe="iron-age"] .field select:focus,
[data-vibe="iron-age"] .field textarea:focus,
[data-vibe="iron-age"] .qty-row input:focus,
[data-vibe="iron-age"] .picker-search input:focus,
[data-vibe="iron-age"] .paste-box:focus { border-color: var(--focus); }
[data-vibe="iron-age"] .qty-row input { font-variation-settings: 'wdth' 100, 'wght' 800; }
/* A placeholder is text: in dim, not the browser's #757575 (3.62:1 on bar).
   Dim is 5.94 on bar and 5.63 on the page, as native's placeholders are. */
[data-vibe="iron-age"] input::placeholder,
[data-vibe="iron-age"] textarea::placeholder { color: var(--dim); opacity: 1; }

/* note · v1: a footnote is its type alone (type.note, dim 13 / 1.5) — no
   ornament before it. */

/* ---------- toast · square ---------- */
[data-vibe="iron-age"] .toast {
  border-radius: 0;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}

/* ---------- settingsRow · ledger ----------
   Label … drawn leader dots … value, and the drawn ›. No rules between rows;
   one hairline under the group. Leaders are Settings' only. */
[data-vibe="iron-age"] .set-list { border-bottom: var(--shape-rule-hair) solid var(--shape-rule-ink); }
[data-vibe="iron-age"] .set-row-nav,
[data-vibe="iron-age"] .set-row-tog { border-top: 0; }
[data-vibe="iron-age"] .set-row-nav { min-height: 44px; }
[data-vibe="iron-age"] .set-row-nav .set-row-l { font-variation-settings: 'wdth' 100, 'wght' 600; }
/* The leader runs only after a label that is one line of words. A label
   holding lines of its own (the owner's account rows: name, email, last
   seen; Coach's goal rows) stays v1's block, so nothing is squeezed. */
[data-vibe="iron-age"] .set-row-nav .set-row-l:not(:has(> *)) {
  display: flex; align-items: baseline; gap: 6px;
}
[data-vibe="iron-age"] .set-row-nav .set-row-l:not(:has(> *))::after {
  content: '';
  flex: 1 1 auto;
  min-width: var(--shape-leader-min);
  height: var(--shape-leader-dot);
  background: radial-gradient(circle, var(--shape-leader-ink) 0 calc(var(--shape-leader-dot) / 2), transparent calc(var(--shape-leader-dot) / 2 + .25px))
    0 0 / var(--shape-leader-pitch) var(--shape-leader-dot) repeat-x;
}
[data-vibe="iron-age"] .set-row-x .glyph { width: 16px; height: 16px; vertical-align: -3px; }
[data-vibe="iron-age"] .set-row-nav:active { background: rgba(var(--lift-rgb), .04); }
/* The switch: off on grip, on in madder, and the knob's side. */
[data-vibe="iron-age"] .tog::after { background: var(--bar); }
[data-vibe="iron-age"] .tog.on { background: var(--accent); }
[data-vibe="iron-age"] .tog.on::after { background: var(--bar); }

/* ---------- listRow · plain ----------
   No rules between rows — the head rules part the groups — on a 44 pitch.
   Names 14/600, values 15/800 tabular, sub-lines 12 dim. */
[data-vibe="iron-age"] .food-entry,
[data-vibe="iron-age"] .pb-row,
[data-vibe="iron-age"] .pr-hit,
[data-vibe="iron-age"] .pr-row,
[data-vibe="iron-age"] .rank-row,
[data-vibe="iron-age"] .sess-row,
[data-vibe="iron-age"] .ex-item,
[data-vibe="iron-age"] .find-row,
[data-vibe="iron-age"] .review-row,
[data-vibe="iron-age"] .rt-pv-row,
[data-vibe="iron-age"] .day-ex,
[data-vibe="iron-age"] .st-row,
[data-vibe="iron-age"] .guide-row,
[data-vibe="iron-age"] .install-step,
[data-vibe="iron-age"] .adm-r,
[data-vibe="iron-age"] .water-entry {
  border-top: 0;
  border-bottom: 0;
  background: none;
  min-height: 44px;
}
[data-vibe="iron-age"] .rt-item,
[data-vibe="iron-age"] .person {
  background: none;
  border: 0;
  border-radius: 0;
  padding-left: 0;
  padding-right: 0;
  margin-bottom: 0;
  min-height: 44px;
}
[data-vibe="iron-age"] .water-entry { padding-left: 0; padding-right: 0; }
[data-vibe="iron-age"] .fe-name,
[data-vibe="iron-age"] .pr-name,
[data-vibe="iron-age"] .rank-name,
[data-vibe="iron-age"] .ex-item .nm,
[data-vibe="iron-age"] .pb-lbl,
[data-vibe="iron-age"] .sess-date { font-variation-settings: 'wdth' 100, 'wght' 600; }
[data-vibe="iron-age"] .fe-cal { font-size: 15px; }
/* A finding's mark: a short printed rule in ink, on the first line's
   x-height, not a round bullet. v1 tints it by subject (you.js sets it
   inline) with no key on the screen; a key-less colour read as decoration
   (the second AI-made panel), so an inset ink shadow covers the inline
   ground: one ink, and no inline value overridden. Its row is v1's. */
[data-vibe="iron-age"] .find-mark {
  width: 12px; height: 3px; border-radius: 0; margin-top: 9px;
  box-shadow: inset 0 0 0 2px var(--chalk);
}
[data-vibe="iron-age"] .sess-row.is-pr { background: rgba(var(--lift-rgb), .06); }
/* A chosen row: the darker leaf plus a drawn tick, never colour alone. */
[data-vibe="iron-age"] .ex-item.sel { background: rgba(var(--lift-rgb), .06); }
[data-vibe="iron-age"] .ex-item.sel::after {
  content: '';
  flex: none;
  width: 6px; height: 11px;
  margin: 0 6px 3px 2px;
  border: solid var(--chalk);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
[data-vibe="iron-age"] .ex-go .glyph,
[data-vibe="iron-age"] .rt-go .glyph { width: 16px; height: 16px; vertical-align: -3px; }
[data-vibe="iron-age"] .ex-del .glyph { width: 13px; height: 13px; vertical-align: -2px; }
[data-vibe="iron-age"] .ex-menu .glyph { width: 18px; height: 18px; vertical-align: -3px; }
/* The drawn ⋯ is shorter than the 18px text line it replaces, so the button
   keeps v1's own height (4 + the line + 4, 33 tall) and never shrinks as a
   target. A button centres what it holds. */
[data-vibe="iron-age"] .ex-menu { min-height: 33px; }

/* Swipe to delete. The rows lie on the page, so the front takes no ground,
   and the Indian-red panel is only there while a row is pulled aside. A
   closed row clips its back out of sight rather than hiding it, so Delete
   stays in the accessibility tree and the tab order as it is in v1 (under
   v1's opaque front) — VoiceOver and a keyboard never make the drag that
   opens a row. Reached from the keyboard, Delete stands over the row's end,
   where an opened row shows it. */
[data-vibe="iron-age"] .swipe-front { background: transparent; }
[data-vibe="iron-age"] .swipe-back { background: none; clip-path: inset(50%); }
[data-vibe="iron-age"] .swipe:has(> .swipe-front[style*="translate"]) > .swipe-back { clip-path: none; }
[data-vibe="iron-age"] .swipe-back:has(> .swipe-del:focus-visible) { clip-path: none; z-index: 1; pointer-events: none; }
[data-vibe="iron-age"] .swipe-back:has(> .swipe-del:focus-visible) > .swipe-del { pointer-events: auto; }
[data-vibe="iron-age"] .swipe-del {
  background: var(--danger);
  font-size: 13px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}

/* ---------- setTable · ruled, setRow · ruled ---------- */
[data-vibe="iron-age"] .ex-block {
  background: none;
  border: 0;
  border-radius: 0;
  margin-bottom: 28px;
}
[data-vibe="iron-age"] .ex-hd { position: relative; padding: 0 0 8px; }
/* The muscle group's plate: a small square swatch before the name, as a
   manual keys a figure to its plate — not a stripe down the side. Its colour
   is v1's inline one. */
[data-vibe="iron-age"] .ex-tag { width: 10px; height: 10px; border-radius: 0; }
[data-vibe="iron-age"] .day-ex-tag { width: 8px; height: 8px; align-self: flex-start; margin-top: 5px; border-radius: 0; }
[data-vibe="iron-age"] .ex-name {
  font-family: var(--font-display);
  font-size: 16px; line-height: 1.2;
  font-variation-settings: 'wght' 600;
  font-synthesis: none;
}
[data-vibe="iron-age"] .ex-prev { padding: 7px 0 8px 14px; font-size: 13px; color: var(--steel); }
[data-vibe="iron-age"] .ex-block .set-hd,
[data-vibe="iron-age"] .ex-block .set-row { padding-left: 0; padding-right: 0; }
[data-vibe="iron-age"] .set-hd,
[data-vibe="iron-age"] .rt-sets .set-hd {
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .ex-block .set-row,
[data-vibe="iron-age"] .rt-sets .set-row { border-top: var(--shape-rule-hair) solid var(--shape-rule-ink); }
[data-vibe="iron-age"] .ex-block .set-hd + .swipe .set-row,
[data-vibe="iron-age"] .rt-sets .set-hd + .swipe .set-row,
[data-vibe="iron-age"] .rt-sets .set-hd + .set-row { border-top-width: var(--shape-rule-sub-0); }
[data-vibe="iron-age"] .ex-block .set-idx,
[data-vibe="iron-age"] .rt-sets .set-idx { background: transparent; color: var(--steel); }
[data-vibe="iron-age"] .ex-block .set-idx.t-W,
[data-vibe="iron-age"] .rt-sets .set-idx.t-W { background: transparent; color: var(--tag-ink-w); }
[data-vibe="iron-age"] .ex-block .set-idx.t-F,
[data-vibe="iron-age"] .rt-sets .set-idx.t-F { background: transparent; color: var(--tag-ink-f); }
[data-vibe="iron-age"] .ex-block .set-idx.t-D,
[data-vibe="iron-age"] .rt-sets .set-idx.t-D { background: transparent; color: var(--tag-ink-d); }
[data-vibe="iron-age"] .set-idx .glyph { width: 13px; height: 13px; }
[data-vibe="iron-age"] .ex-block .set-row input,
[data-vibe="iron-age"] .rt-sets .set-row input {
  background: transparent;
  border-color: transparent transparent var(--chalk);
  border-radius: 0;
}
[data-vibe="iron-age"] .ex-block .set-row input:focus,
[data-vibe="iron-age"] .rt-sets .set-row input:focus { border-color: transparent transparent var(--focus); background: rgba(var(--accent-rgb), .06); }
[data-vibe="iron-age"] .set-e1rm { font-size: 12px; }
[data-vibe="iron-age"] .set-check { border-radius: 0; }
[data-vibe="iron-age"] .set-check .glyph { width: 16px; height: 16px; }
[data-vibe="iron-age"] .ex-block .set-row.flash { animation-name: iron-age-set-flash; }
@keyframes iron-age-set-flash {
  0%   { background: rgba(var(--accent-rgb), .14); }
  100% { background: rgba(var(--done-rgb), .07); }
}
[data-vibe="iron-age"] .set-row.drop::before { border-radius: 0; background: rgba(var(--p-blue-rgb), .75); }
[data-vibe="iron-age"] .drop-add { border-color: transparent; }
[data-vibe="iron-age"] .ex-actions { padding: 10px 0 0; }
[data-vibe="iron-age"] .swipe-hint { padding-left: 14px; }
/* …and at full strength: dim at v1's .65 is 2.77:1 on the page; solid it is
   5.63 (5.94 on bar). The Coach nudge that shares the class is already 1. */
[data-vibe="iron-age"] .swipe-hint { opacity: 1; }

/* A lifting block: framed by the double rule above and below its
   exercises, under its title in Besley SemiBold 15, ink. */
[data-vibe="iron-age"] .wk-block,
[data-vibe="iron-age"] .rt-pv-block {
  border: 0;
  border-radius: 0;
  padding-top: 5px;
  padding-bottom: 5px;
  background:
    -webkit-image-set(url(iron-age/textures/rule-total@2x.png) 2x, url(iron-age/textures/rule-total@3x.png) 3x) 0 -1px / 144px 6px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-total-0) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-total-0) + var(--shape-rule-total-1)) / 100% var(--shape-rule-total-2) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 100% / 100% var(--shape-rule-total-2) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(100% - var(--shape-rule-total-2) - var(--shape-rule-total-1)) / 100% var(--shape-rule-total-0) no-repeat;
}
[data-vibe="iron-age"] .wk-block-body { padding-left: 0; padding-right: 0; }
[data-vibe="iron-age"] .wk-block-hd { padding-left: 0; padding-right: 0; }
[data-vibe="iron-age"] .wk-block-title {
  font-family: var(--font-display);
  font-size: 15px; letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wght' 600;
  font-synthesis: none;
}

/* ---------- plateStrip · stamp ----------
   Each plate a stamped square: a 1pt keyline in its own plate's ink, no
   fill, the figures in ink. The plate's colour is the chip's inline
   background (workout.js renderPlates); the chip keeps it in its 1pt border
   (background-clip border-box under a transparent border) and covers the
   rest with the page, so no inline value is overridden. */
[data-vibe="iron-age"] .plate-strip { padding-left: 14px; padding-right: 0; gap: 5px; }
[data-vibe="iron-age"] .plate-strip .lbl {
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .plate-chip {
  border: var(--shape-keyline-width) solid transparent;
  background-clip: border-box;
  box-shadow: inset 0 0 0 20px var(--rack);
  color: var(--chalk);
  font-size: 12px;
  font-variation-settings: 'wdth' 100, 'wght' 800;
}

/* ---------- calCell · ruled: a printed calendar ---------- */
[data-vibe="iron-age"] .cal-dow { gap: 0; }
[data-vibe="iron-age"] .cal-dow span {
  font-size: 11px; letter-spacing: 0;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .cal-grid {
  gap: 0;
  border-top: var(--shape-rule-hair) solid var(--shape-rule-ink);
  border-left: var(--shape-rule-hair) solid var(--shape-rule-ink);
}
[data-vibe="iron-age"] .cal-day,
[data-vibe="iron-age"] .cal-day.empty,
[data-vibe="iron-age"] .cal-day.has-work {
  background: none;
  border: 0;
  border-right: var(--shape-rule-hair) solid var(--shape-rule-ink);
  border-bottom: var(--shape-rule-hair) solid var(--shape-rule-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .cal-day.pad { visibility: visible; }
[data-vibe="iron-age"] .cal-day.today { box-shadow: inset 0 0 0 2px var(--chalk); }
[data-vibe="iron-age"] .cal-daynum { font-variation-settings: 'wdth' 100, 'wght' 600; }
[data-vibe="iron-age"] .cal-day.has-work .cal-daynum { color: var(--chalk); font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .cal-day.today .cal-daynum { color: var(--chalk); font-variation-settings: 'wdth' 100, 'wght' 800; }
[data-vibe="iron-age"] .cal-legend-item { color: var(--steel); }

/* ---------- chart · print ----------
   2pt lines with square ends and no area or glow; square-topped bars; the
   day that is not over hatched in its own colour (vibe.js's patterns) in
   place of dimmed; targets dashed in ink; a collar grid; rings with butt
   ends; axis text at 11. analytics.js is pinned: this restyles what it
   draws and adds no geometry. */
[data-vibe="iron-age"] .chart path[stroke="none"][fill^="url(#"],
[data-vibe="iron-age"] .spark-glow { display: none; }
[data-vibe="iron-age"] .chart-line { stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter; }
[data-vibe="iron-age"] .chart-line2 { stroke-linecap: butt; stroke-linejoin: miter; opacity: 1; }
[data-vibe="iron-age"] .spark-line,
[data-vibe="iron-age"] .spark-line-dim { stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter; }
[data-vibe="iron-age"] .chart-grid { stroke: var(--collar); stroke-width: 1; stroke-dasharray: none; opacity: 1; }
[data-vibe="iron-age"] .chart-bar,
[data-vibe="iron-age"] .chart-bar-bg,
[data-vibe="iron-age"] .spark-bar,
[data-vibe="iron-age"] .chart clipPath rect,
[data-vibe="iron-age"] .heat rect { rx: 0; ry: 0; }
[data-vibe="iron-age"] .chart-bar-bg { opacity: .6; }
[data-vibe="iron-age"] .chart-target,
[data-vibe="iron-age"] .spark-ref { stroke: var(--chalk); opacity: 1; }
[data-vibe="iron-age"] .chart-axis,
[data-vibe="iron-age"] .chart-barval,
[data-vibe="iron-age"] .chart-peak-lbl {
  font-size: 11px; letter-spacing: 0;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .chart-barval { font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .chart-peak-lbl { font-variation-settings: 'wdth' 100, 'wght' 800; }
/* The peak's figure is small text in the line's colour (analytics.js, pinned,
   fills it with the chart's own var): a graphic-only plate is inked through
   inkOf, ochre as warn (5.74:1 where ochre is 3.92) and pewter as steel. */
[data-vibe="iron-age"] .chart-peak-lbl[fill="var(--p-yellow)"] { fill: var(--warn); }
[data-vibe="iron-age"] .chart-peak-lbl[fill="var(--p-chrome)"] { fill: var(--steel); }
[data-vibe="iron-age"] .donut-sub,
[data-vibe="iron-age"] .ring-sub { letter-spacing: 0; text-transform: none; }
[data-vibe="iron-age"] .donut-sub { font-size: 11px; font-variation-settings: 'wdth' 100, 'wght' 600; }
[data-vibe="iron-age"] .ring-fill,
[data-vibe="iron-age"] .st-ring circle { stroke-linecap: butt; }
[data-vibe="iron-age"] .st-ring-s { font-size: 11px; letter-spacing: 0; }
/* The Steps ring as a dial, not a dashboard donut: the track is the dial's
   face, sixty 1.2pt ticks in knurl (a graphic, 3.52:1), and the day's arc a
   6pt line in its plate laid over them, butt-ended. Same circle, radius and
   fraction as v1's. */
[data-vibe="iron-age"] .st-ring circle:first-child { stroke: var(--knurl); stroke-dasharray: 1.2 4.455; }
[data-vibe="iron-age"] .st-ring circle + circle { stroke-width: 6; }
/* Green on Steps is the goal met, as the chart's own footnote says ("green =
   goal met"). Iron Age's steps plate (pGreen) and its good are one viridian,
   so a day short of the goal drew green too and the footnote was not true to
   the eye. On this tab a day short of the goal is drawn in the Steps
   subject's plate, ink (subjects.steps, pWhite) — the ring's arc, the bars,
   the heat strip — and the goal met stays good. steps.js sets both colours
   inline; SVG presentation attributes lose to any author rule. */
[data-vibe="iron-age"] #view-steps .st-ring circle[stroke="var(--p-green)"] { stroke: var(--p-white); }
[data-vibe="iron-age"] #view-steps rect.chart-bar[fill="var(--p-green)"],
[data-vibe="iron-age"] #view-steps .heat rect[fill="var(--p-green)"] { fill: var(--p-white); }
/* One hero figure on the card: the ring's count. The steps to go are the
   side's running line — Archivo 17/700, tabular, its colour steps.js's
   inline one — not a second hero beside the ring (the second AI-made
   panel). V59 §5.9: the size beats steps.js renderToday's inline
   `big.style.fontSize = '26px'`. */
[data-vibe="iron-age"] .st-hero-side .load-num {
  font-family: var(--font);
  font-size: 17px !important; /* beats steps.js renderToday: big.style.fontSize = '26px' */
  line-height: 1.2;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}
[data-vibe="iron-age"] .chart-empty { border-color: var(--knurl); }
[data-vibe="iron-age"] .wc-avg { stroke-linecap: square; stroke-linejoin: miter; }
/* The day that is not over: hatched at 45° in its own colour. */
[data-vibe="iron-age"] rect.chart-bar-dim,
[data-vibe="iron-age"] g.chart-bar-dim { opacity: 1; }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-red)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-red)"] { fill: url(#vibe-hatch-p-red); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-blue)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-blue)"] { fill: url(#vibe-hatch-p-blue); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-yellow)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-yellow)"] { fill: url(#vibe-hatch-p-yellow); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-green)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-green)"] { fill: url(#vibe-hatch-p-green); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-white)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-white)"] { fill: url(#vibe-hatch-p-white); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--p-chrome)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--p-chrome)"] { fill: url(#vibe-hatch-p-chrome); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--good)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--good)"] { fill: url(#vibe-hatch-good); }
[data-vibe="iron-age"] rect.chart-bar-dim[fill="var(--bad)"],
[data-vibe="iron-age"] g.chart-bar-dim rect[fill="var(--bad)"] { fill: url(#vibe-hatch-bad); }
/* Macros: protein solid, carbs a 45° hatch in its own ochre — the stacked
   bars' carbs part too, from the same patterns. */
[data-vibe="iron-age"] g.chart-bar:not(.chart-bar-dim) rect[fill="var(--p-yellow)"] { fill: url(#vibe-hatch-p-yellow); }

/* The heat strip (analytics.js heatStrip, steps.js heatMap; both pinned or
   duplicated, both paint a trained day at fill-opacity .28 + .72·v/max). On
   cream an ochre cell at .28 is 1.40:1 and collar's near-twin, and even solid
   ochre is 3.92, which leaves no room for a scale. So a training day is
   inked in warn, the ochre's own dark (inkOf), and every trained cell's
   opacity a is remapped to .70 + .30·(a − .28)/.72 — linear, monotonic, 1 at
   1 — so the faintest is 3.11:1 on the page (3.02 on the grain's darkest
   pixel, 2.10 against an untrained cell) and the heaviest 5.74. Steps' strip
   is inked in its subject's plate (above) and takes the same remap. Native
   draws the same numbers (src/ui/chart/HeatStrip.jsx, chart · print); the
   arithmetic is tools vibe-contrast ia-rs9-heat. SVG presentation
   attributes lose to any author rule. */
[data-vibe="iron-age"] .heat rect[fill="var(--p-yellow)"] { fill: var(--warn); }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.28"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.29"] { fill-opacity: .70; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.30"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.31"] { fill-opacity: .71; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.32"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.33"] { fill-opacity: .72; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.34"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.35"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.36"] { fill-opacity: .73; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.37"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.38"] { fill-opacity: .74; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.39"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.40"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.41"] { fill-opacity: .75; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.42"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.43"] { fill-opacity: .76; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.44"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.45"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.46"] { fill-opacity: .77; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.47"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.48"] { fill-opacity: .78; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.49"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.50"] { fill-opacity: .79; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.51"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.52"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.53"] { fill-opacity: .80; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.54"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.55"] { fill-opacity: .81; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.56"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.57"] { fill-opacity: .82; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.58"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.59"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.60"] { fill-opacity: .83; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.61"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.62"] { fill-opacity: .84; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.63"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.64"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.65"] { fill-opacity: .85; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.66"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.67"] { fill-opacity: .86; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.68"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.69"] { fill-opacity: .87; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.70"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.71"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.72"] { fill-opacity: .88; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.73"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.74"] { fill-opacity: .89; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.75"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.76"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.77"] { fill-opacity: .90; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.78"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.79"] { fill-opacity: .91; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.80"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.81"] { fill-opacity: .92; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.82"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.83"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.84"] { fill-opacity: .93; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.85"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.86"] { fill-opacity: .94; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.87"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.88"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.89"] { fill-opacity: .95; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.90"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.91"] { fill-opacity: .96; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.92"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.93"] { fill-opacity: .97; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.94"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.95"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.96"] { fill-opacity: .98; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.97"],
[data-vibe="iron-age"] .heat rect[fill-opacity="0.98"] { fill-opacity: .99; }
[data-vibe="iron-age"] .heat rect[fill-opacity="0.99"] { fill-opacity: 1; }

/* meters: square-ended on a square tan track */
[data-vibe="iron-age"] .vol-track,
[data-vibe="iron-age"] .vol-fill,
[data-vibe="iron-age"] .traj-bar,
[data-vibe="iron-age"] .traj-fill { border-radius: 0; }
[data-vibe="iron-age"] .fuel-sum .cal-meter + .vol-row + .vol-row .vol-fill,
[data-vibe="iron-age"] .macro-rows .vol-row:nth-child(2) .vol-fill,
[data-vibe="iron-age"] .card:has(.macro-rows) .legend-inline .legend-item:nth-child(2) i {
  -webkit-mask-image: repeating-linear-gradient(45deg, #000 0 1.25px, transparent 1.25px 2.75px);
  mask-image: repeating-linear-gradient(45deg, #000 0 1.25px, transparent 1.25px 2.75px);
}
/* …and fat a dot screen, at the same 2.75 pitch. */
[data-vibe="iron-age"] .fuel-sum .cal-meter + .vol-row + .vol-row + .vol-row .vol-fill,
[data-vibe="iron-age"] .macro-rows .vol-row:nth-child(3) .vol-fill,
[data-vibe="iron-age"] .card:has(.macro-rows) .legend-inline .legend-item:nth-child(3) i {
  -webkit-mask-image: radial-gradient(circle, #000 0 1.05px, transparent 1.25px);
  -webkit-mask-size: 2.75px 2.75px;
  mask-image: radial-gradient(circle, #000 0 1.05px, transparent 1.25px);
  mask-size: 2.75px 2.75px;
}
[data-vibe="iron-age"] .fuel-sum .vol-track { height: 8px; }

/* The calorie meter. A square tan track; the three bands as full-strength
   patterns, pitch 2.75: cut a 45° Prussian hatch, hold an ochre dot screen,
   gain a 135° Indian-red hatch (a wash on cream loses its hue, and the copy
   says "Blue — cut"). The eaten part solid; the white head, the ticks and
   the dashed target white with a 1pt ink edge (shadow.calTick / calHead /
   calTarget). */
[data-vibe="iron-age"] .cal-track { overflow: visible; }
[data-vibe="iron-age"] .cal-zone.cut,
[data-vibe="iron-age"] .guide-sw.cut {
  background: repeating-linear-gradient(45deg, var(--p-blue) 0 1px, transparent 1px 2.75px), var(--track);
}
[data-vibe="iron-age"] .cal-zone.hold,
[data-vibe="iron-age"] .guide-sw.hold {
  background: radial-gradient(circle, var(--p-yellow) 0 .85px, transparent 1.05px) 0 0 / 2.75px 2.75px, var(--track);
}
[data-vibe="iron-age"] .cal-zone.gain,
[data-vibe="iron-age"] .guide-sw.gain {
  background: repeating-linear-gradient(135deg, var(--p-red) 0 1px, transparent 1px 2.75px), var(--track);
}
[data-vibe="iron-age"] .cal-fill { opacity: 1; }
[data-vibe="iron-age"] .cal-tick { opacity: 1; }
[data-vibe="iron-age"] .cal-target { opacity: 1; }
[data-vibe="iron-age"] .cal-band-lab {
  font-size: 11px; line-height: 13px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .guide-sw.macro {
  background:
    linear-gradient(var(--p-red), var(--p-red)) 0 0 / 34% 100% no-repeat,
    repeating-linear-gradient(45deg, var(--p-yellow) 0 1.25px, transparent 1.25px 2.75px) 0 0 / 67% 100% no-repeat,
    var(--p-blue);
}
[data-vibe="iron-age"] .guide-sw.big { background: var(--p-blue); }

/* The confidence dot: shape as well as colour — filled (confident), half (a
   fair guess), a ring (a rough guess) — beside its word. No pill round it. */
[data-vibe="iron-age"] .conf {
  border: 0; border-radius: 0;
  padding-left: 0;
  font-size: 12px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .conf i { width: 10px; height: 10px; }
[data-vibe="iron-age"] .conf i[style*="--warn"] {
  -webkit-mask-image: linear-gradient(90deg, #000 50%, transparent 50%), radial-gradient(circle, transparent 3.2px, #000 3.4px);
  mask-image: linear-gradient(90deg, #000 50%, transparent 50%), radial-gradient(circle, transparent 3.2px, #000 3.4px);
}
[data-vibe="iron-age"] .conf i[style*="--bad"] {
  -webkit-mask-image: radial-gradient(circle, transparent 3.2px, #000 3.4px);
  mask-image: radial-gradient(circle, transparent 3.2px, #000 3.4px);
}
/* The estimate's total under the double rule. */
[data-vibe="iron-age"] div:has(> .conf) > .entry-readout {
  padding-top: calc(var(--shape-rule-total-0) + var(--shape-rule-total-1) + var(--shape-rule-total-2) + 8px);
  background:
    -webkit-image-set(url(iron-age/textures/rule-total@2x.png) 2x, url(iron-age/textures/rule-total@3x.png) 3x) 0 -1px / 144px 6px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-total-0) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-total-0) + var(--shape-rule-total-1)) / 100% var(--shape-rule-total-2) no-repeat;
}

/* ---------- dock · rail ----------
   Opaque paper under a 2pt ink rule; the solid cuts at 22 (no stroke)
   over 11/600 labels, as written. Active: a 3pt ink bar the cell's full
   width along the rule, icon and label in ink, the label 700. The dock's
   tabs, order, height and place never change. */
[data-vibe="iron-age"] .dock {
  background: var(--bar);
  border-top: 2px solid var(--shape-rule-ink);
}
[data-vibe="iron-age"] .dock button {
  font-size: 11px;
  letter-spacing: .01em;
  text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
/* The dock's five are solid cuts: the dock sets the width (cssStroke), so
   it sets none. */
[data-vibe="iron-age"] .dock button svg { stroke-width: 0; }
[data-vibe="iron-age"] .dock button.active { font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .dock button.active::before {
  left: 0; right: 0; top: 0;
  width: auto; height: 3px;
  transform: none;
  border-radius: 0;
  background: var(--chalk);
  animation: none;
}
[data-vibe="iron-age"] #dock button.tour-lit::after { border-radius: 0; }

/* ---------- fab · inverse ----------
   A square ink block, the Greek cross and "Log food" as written, knocked
   out; no shadow; pressed .955 as v1. */
[data-vibe="iron-age"] .fuel-fab,
[data-vibe="iron-age"] .fuel-fab:active {
  background: var(--inverse);
  color: var(--knockout);
}
[data-vibe="iron-age"] .fuel-fab {
  border-radius: 0;
  letter-spacing: .01em;
  text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}

/* ---------- addTile · ruled ----------
   No tiles: a two-column grid parted by hairlines, each cell an index entry
   — the engraved cut at 22 with no well, inline before the title, the "ai"
   note run in after the title, the line under both. (A cut stacked over its
   title with a tag in the corner read as the feature-card grid, the second
   AI-made panel.) The Photo cut is printed in madder, the sheet's one red,
   with no square behind it. The cells, their order and their two columns
   are v1's. */
[data-vibe="iron-age"] .add-grid {
  gap: 0;
  border-top: var(--shape-rule-hair) solid var(--shape-rule-ink);
}
[data-vibe="iron-age"] .add-tile,
[data-vibe="iron-age"] .add-tile.hero,
[data-vibe="iron-age"] .add-tile.lit,
[data-vibe="iron-age"] .add-tile:active,
[data-vibe="iron-age"] .add-tile:disabled:active {
  background: none;
  border: 0;
  border-bottom: var(--shape-rule-hair) solid var(--shape-rule-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .add-tile:nth-child(odd) { border-right: var(--shape-rule-hair) solid var(--shape-rule-ink); }
[data-vibe="iron-age"] .add-tile {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: center; align-content: start;
  column-gap: 8px; row-gap: 6px;
  padding: 14px 14px 14px 12px;
}
[data-vibe="iron-age"] .add-tile:nth-child(odd) { padding-left: 0; }
[data-vibe="iron-age"] .add-tile > .ic { grid-column: 1; grid-row: 1; }
[data-vibe="iron-age"] .add-tile > .t { grid-column: 2; grid-row: 1; min-width: 0; }
[data-vibe="iron-age"] .add-tile > .tag { grid-column: 3; grid-row: 1; justify-self: start; }
[data-vibe="iron-age"] .add-tile > .d { grid-column: 1 / -1; grid-row: 2; }
[data-vibe="iron-age"] .add-tile .ic,
[data-vibe="iron-age"] .add-tile.lit .ic {
  width: auto; height: auto;
  background: none;
  color: var(--chalk);
  border-radius: 0;
}
[data-vibe="iron-age"] .add-tile.hero .ic { background: none; color: var(--accent); }
[data-vibe="iron-age"] .add-tile .ic svg { width: 22px; height: 22px; stroke-width: 0; }
[data-vibe="iron-age"] .add-tile .t { font-size: 15px; font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .add-tile .d { font-size: 13px; }
/* The "ai" tag: the word as written, in the running meta (type.meta,
   Archivo 13 roman, steel) — a note run in after the title, no box, not
   pinned to the corner. */
[data-vibe="iron-age"] .add-tile .tag,
[data-vibe="iron-age"] .add-tile.lit .tag {
  position: static;
  padding: 0;
  background: none;
  color: var(--steel);
  border: 0;
  border-radius: 0;
  font-family: var(--font);
  font-size: 13px; line-height: 1.35; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 400;
}
[data-vibe="iron-age"] .add-rule { height: 0; background: none; border-top: var(--shape-rule-hair) solid var(--shape-rule-ink); }
/* The estimator notices: a keyline callout, the printers' fist in warn
   pointing at its sentence in ink. No yellow wash, no sparkle. */
[data-vibe="iron-age"] .ai-warn {
  background: none;
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
  color: var(--chalk);
  font-size: 12px;
}
[data-vibe="iron-age"] .ai-warn svg { color: var(--warn); width: 18px; height: 18px; }
[data-vibe="iron-age"] .ai-shot { border-color: var(--shape-keyline-ink); }

/* ---------- sessionChrome · plate ----------
   The top bar: bar paper under a 1pt ink rule (the status band above it
   stays ink, the generated strip). The clock tabular steel; the live chip
   and the calendar button 38, square keyline plates; Finish the ink block.
   The rest pill and the peek bar are square plates with a keyline and no
   shadow. Every target at least v1's. */
[data-vibe="iron-age"] .wk-bar {
  background: var(--bar);
  border-bottom: 1px solid var(--shape-rule-ink);
}
[data-vibe="iron-age"] .wk-name { font-size: 15px; font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .timer { font-variation-settings: 'wdth' 100, 'wght' 700; letter-spacing: 0; }
[data-vibe="iron-age"] .wk-bar .timer { color: var(--steel); }
/* The live chip and the calendar button: bare cuts, as the month buttons are
   — no ground, no keyline; pressed, a leaf of raised paper shows the target
   (a grey slug behind each read as an icon in a tinted box, the second
   AI-made panel). Finish is the bar's one boxed thing, the ink block. The
   chip's word is written "Coach" (coach-ui.js): shown as written, 12/700 in
   ink, untracked — the rubric is its balloon. v1's 38s kept. */
[data-vibe="iron-age"] .wk-coach,
[data-vibe="iron-age"] .wk-cal-btn {
  background: none;
  border-color: transparent;
  border-radius: 0;
}
[data-vibe="iron-age"] .wk-coach .coach-ttl {
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wdth' 100, 'wght' 700;
}
[data-vibe="iron-age"] .wk-cal-btn { color: var(--chalk); margin-right: 6px; }
[data-vibe="iron-age"] .wk-cal-btn svg { stroke-width: 0; }
[data-vibe="iron-age"] .wk-coach:active,
[data-vibe="iron-age"] .wk-cal-btn:active { background: var(--raised); border-color: transparent; }
[data-vibe="iron-age"] .rest-pill,
[data-vibe="iron-age"] .peek-bar {
  background: var(--bar);
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .rest-pill .t {
  font-size: 22px;
  font-variation-settings: 'wdth' 100, 'wght' 800;
  font-feature-settings: 'tnum' 1;
}
[data-vibe="iron-age"] .rest-pill button { color: var(--chalk); font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .rest-pill button:last-child {
  color: var(--steel);
  text-decoration: underline;
  text-underline-offset: 3px;
}
[data-vibe="iron-age"] .peek-name { font-variation-settings: 'wdth' 100, 'wght' 700; }

/* The Coach nudge under a finished exercise: a paper strip between two
   hairlines (drawn as shadows, so the row it shares never moves), ink words,
   the drawn saltire. */
[data-vibe="iron-age"] .swipe-hint.coach-nudge {
  background: var(--bar);
  box-shadow: inset 0 var(--shape-rule-hair) 0 var(--shape-rule-ink), inset 0 calc(-1 * var(--shape-rule-hair)) 0 var(--shape-rule-ink);
}
[data-vibe="iron-age"] .coach-nudge-t { color: var(--chalk); }
[data-vibe="iron-age"] .coach-nudge-x .glyph { width: 11px; height: 11px; }

/* ---------- the Coach sheet ----------
   Rack's lines are text under the article rule (shape.rule.sub, ink), the
   column's full width, no ground — a grey inset callout read as a generic
   panel (the second AI-made panel); the question keeps its madder rule at
   the left, its words 10 in. His replies are ink blocks with the words
   knocked out; Pro's panel a keyline block, no madder wash. */
[data-vibe="iron-age"] .coach-bub,
[data-vibe="iron-age"] .coach-bub.you { border-radius: 0; }
[data-vibe="iron-age"] .coach-bub:not(.you):not(.pro) {
  align-self: stretch; max-width: 100%;
  background: none;
  padding: 10px 0 4px;
  border-top: var(--shape-rule-sub-0) solid var(--shape-rule-ink);
}
[data-vibe="iron-age"] .coach-bub.ask:not(.you):not(.pro) { padding-left: 10px; }
[data-vibe="iron-age"] .coach-bub.you { background: var(--inverse); border: 0; }
[data-vibe="iron-age"] .coach-bub.you .coach-bub-t { color: var(--knockout); }
[data-vibe="iron-age"] .coach-bub.pro {
  background: var(--raised);
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
}
[data-vibe="iron-age"] .coach-build-target { color: var(--chalk); }

/* ---------- the other You cards ---------- */
[data-vibe="iron-age"] .review-verdict {
  font-family: var(--font-display);
  font-size: 24px; letter-spacing: 0;
  font-variation-settings: 'wght' 800;
  font-synthesis: none;
}
/* "Next week": the period's boxed note, a 1pt ink keyline and no fill. */
[data-vibe="iron-age"] .review-take {
  background: none;
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .review-take .chart-sub { color: var(--chalk); }
[data-vibe="iron-age"] .thesis-eq { border-top: var(--shape-rule-hair) solid var(--shape-rule-ink); }
[data-vibe="iron-age"] .thesis-eq .thesis-op,
[data-vibe="iron-age"] .thesis-eq b { color: var(--ink-of-p-yellow); }
[data-vibe="iron-age"] .install-n { border-radius: 0; }
[data-vibe="iron-age"] .st-flame { border-radius: 0; }
[data-vibe="iron-age"] .st-flame.on { background: var(--inverse); color: var(--knockout); box-shadow: none; }
[data-vibe="iron-age"] .group-pill {
  background: none;
  border-color: var(--shape-keyline-ink);
  border-radius: 0;
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .day-title {
  font-family: var(--font-display);
  font-size: 16px;
  font-variation-settings: 'wght' 600;
  font-synthesis: none;
}

/* ---------- water ---------- */
[data-vibe="iron-age"] .water-vessel > path[stroke] { stroke: var(--chalk); }
[data-vibe="iron-age"] .water-preset {
  background: none;
  border-color: var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .water-preset:active { background: var(--raised); border-color: var(--shape-keyline-ink); }
[data-vibe="iron-age"] .wpe-del { border-color: var(--shape-keyline-ink); color: var(--chalk); }
[data-vibe="iron-age"] .water-pip { border-color: var(--chalk); }

/* ---------- toasts, sync pip, trial bar ---------- */
[data-vibe="iron-age"] .trial-bar {
  border-radius: 0;
  background: rgba(var(--warn-rgb), .12);
  border-color: var(--warn);
  font-size: 11px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 700;
}

/* ---------- admin (the owner's panel): legible, not ornamented ---------- */
[data-vibe="iron-age"] .adm-flag {
  border-radius: 0;
  border-color: currentColor;
  font-size: 11px; letter-spacing: 0; text-transform: none;
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
[data-vibe="iron-age"] .adm-flag.on,
[data-vibe="iron-age"] .adm-flag.off,
[data-vibe="iron-age"] .adm-flag.lit,
[data-vibe="iron-age"] .adm-flag.warn { border-color: currentColor; }
[data-vibe="iron-age"] .adm-flag:not(.on):not(.off):not(.lit):not(.warn) { color: var(--steel); }

/* ---------- sign-in and the gates (web only) ----------
   The stock, the ink status band, the six-plate mark in plate inks each
   square-cut with an ink keyline, the title in Besley with no device under
   it, square fields, the ink primary, links as underlined steel words. */
[data-vibe="iron-age"] .auth-mark i { border-radius: 0; box-shadow: 0 0 0 1px var(--chalk); }
[data-vibe="iron-age"] .auth-title,
[data-vibe="iron-age"] .gate-title {
  font-size: 24px;
  font-variation-settings: 'wght' 800;
}
[data-vibe="iron-age"] .gate-pending {
  background: none;
  border-color: var(--shape-keyline-ink);
  border-radius: 0;
  color: var(--chalk);
}
[data-vibe="iron-age"] .gate-sep::before,
[data-vibe="iron-age"] .gate-sep::after { height: 0; background: none; border-top: var(--shape-rule-hair) solid var(--shape-rule-ink); }
[data-vibe="iron-age"] .gate-who { border-top: var(--shape-rule-hair) solid var(--shape-rule-ink); }

/* ---------- onboarding (8 steps) and the tour ----------
   The kicker the small roman running head, the title Besley. Choice cards a
   square ink keyline; chosen a 2pt keyline and a drawn tick — never colour
   alone. Progress in ink. The tour: the flat ink veil (scrim.tour), the card
   bar paper in a keyline with the head rule on top, the lit tab ringed in
   madder. */
[data-vibe="iron-age"] .ob-card {
  border-color: var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .ob-fill { background: var(--chalk); }
[data-vibe="iron-age"] .ob-title {
  font-size: 24px;
  font-variation-settings: 'wght' 800;
}
[data-vibe="iron-age"] .ob-item-t {
  font-size: 12px; letter-spacing: 0; text-transform: none;
  color: var(--chalk);
  font-variation-settings: 'wdth' 100, 'wght' 800;
}
[data-vibe="iron-age"] .ob-choice {
  position: relative;
  background: var(--bar);
  border-color: var(--shape-keyline-ink);
  border-radius: 0;
  padding-right: 40px;
}
[data-vibe="iron-age"] .ob-choice.on {
  background: var(--bar);
  border-color: var(--shape-keyline-ink);
  box-shadow: inset 0 0 0 1px var(--shape-keyline-ink);
}
[data-vibe="iron-age"] .ob-choice.on::after {
  content: '';
  position: absolute; right: 17px; top: 50%;
  width: 6px; height: 12px;
  margin-top: -8px;
  border: solid var(--chalk);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
[data-vibe="iron-age"] .ob-choice-t { font-variation-settings: 'wdth' 100, 'wght' 700; }
[data-vibe="iron-age"] .ob-choice-d { color: var(--dim); }
[data-vibe="iron-age"] .ob-num {
  background: var(--bar);
  border-color: var(--knurl);
  border-radius: 0;
}
[data-vibe="iron-age"] .ob-num-l { font-size: 11px; letter-spacing: 0; }
[data-vibe="iron-age"] .ob-num-s { font-size: 11px; }
[data-vibe="iron-age"] .ob-tip {
  background: none;
  border: var(--shape-keyline-width) solid var(--shape-keyline-ink);
  border-radius: 0;
}
[data-vibe="iron-age"] .ob-adjust summary { text-decoration-color: var(--steel); }
[data-vibe="iron-age"] .ob-dots i {
  width: 9px; height: 9px;
  border-radius: 0;
  background: none;
  box-shadow: inset 0 0 0 1px var(--chalk);
}
[data-vibe="iron-age"] .ob-dots i.on { background: var(--chalk); }
[data-vibe="iron-age"] .ob-tour-card {
  padding-top: 24px;
  background:
    -webkit-image-set(url(iron-age/textures/rule-sub@2x.png) 2x, url(iron-age/textures/rule-sub@3x.png) 3x) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1) - 1px) / 144px 3px repeat-x,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 0 / 100% var(--shape-rule-head-2) no-repeat,
    linear-gradient(var(--shape-rule-ink), var(--shape-rule-ink)) 0 calc(var(--shape-rule-head-2) + var(--shape-rule-head-1)) / 100% var(--shape-rule-head-0) no-repeat,
    var(--bar);
}

/* ---------- the tailpiece: one traced ornament at a screen's foot, in ink ---------- */
[data-vibe="iron-age"] .tailpiece { color: var(--chalk); }

/* ---------- the Vibes sheet, worn ----------
   Square tiles; the vibe worn marked by a 3pt ink rule flush round its tile
   and the check inside — a heavier rule, not a rounded ring clear of it. */
[data-vibe="iron-age"] .vibe-tile { border-radius: 0; }
[data-vibe="iron-age"] .vibe-tile[aria-current="true"] { box-shadow: 0 0 0 3px var(--chalk); }

/* ---------- the Vibes sheet: Iron Age's own tile ----------
   The stock ground with its grain; the sample card in cardSkin (bar, collar,
   square); `315` in Besley over the naval-gym thumbnail under the stock .54
   scrim (4.54:1 against its worst pixel as Chrome draws it); the madder
   bar. The scrim sits over the photo and under the figure and the bar. */
[data-vibe="iron-age"].vibe-in {
  border-radius: 0;
  background-image: url(iron-age/textures/grain-manual@3x.png);
  background-image: -webkit-image-set(url(iron-age/textures/grain-manual@2x.png) 2x, url(iron-age/textures/grain-manual@3x.png) 3x);
  background-size: 72px 72px;
}
[data-vibe="iron-age"].vibe-in .vibe-sample.photo::after {
  content: '';
  position: absolute; inset: 0;
  background: rgba(var(--rack-rgb), .54);
}
[data-vibe="iron-age"].vibe-in .vibe-num,
[data-vibe="iron-age"].vibe-in .vibe-accent { z-index: 1; }
[data-vibe="iron-age"].vibe-in .vibe-num {
  font-variation-settings: 'wght' 800;
  letter-spacing: 0;
  font-synthesis: none;
}
