/* ============================================================================
   THE ELEVEN DIRECTIONS.

   Read styles.js first; it records why this file exists and what the previous
   attempt got wrong. The short version: a direction is type, motion, surface,
   composition and one signature mechanism. The first attempt varied colour and
   the result was identified as "just color changing option" on sight.

   So every block below is required to change at least FOUR of these five, and
   most change all five:

     TYPE         a different --disp / --mono, a different size ramp, a
                  different weight. Not Archivo in a new tint.
     MOTION       --ease and the four --d-* durations. A 120ms app and an 800ms
                  app are different apps.
     SURFACE      --rad / --radb / --radt, and whether a row is a filled card,
                  a hairline rule, or nothing at all.
     COMPOSITION  what the home screen IS. .metarow goes from three columns to a
                  stacked list; .bugwrap disappears entirely in the quiet ones;
                  .hero loses its gradient, its diagonal and its border.
     SIGNATURE    the .sig* classes, rendered by screens.js only for the style
                  that owns them.

   Every value was read out of the prototype named in the heading, in ../apps/,
   rather than invented here.

   CONTRAST. --t1/--t2/--t3 were checked against each style's own --bg, --panel
   and --panel2 at 4.5:1, and every --onX pair against the fill it sits on. The
   four light styles were the work: they need --onRed and --onGold inverted,
   --track and --press re-grounded, and --hero flattened, which is exactly the
   set of values the base sheet had typed in place until this file needed them.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   Shared de-broadcasting. These four things are Broadcast's own signature and
   are wrong in all ten others: the variable-width display axis, the navy
   gradient, the decorative diagonal, and the radial wash behind the hero.
   Broadcast keeps them because it IS :root and is never selected here.
   --------------------------------------------------------------------------- */
html[data-style] .disp,
html[data-style] .wordmark,
html[data-style] .chan-title,
html[data-style] .btn,
html[data-style] .bug .bh{font-stretch:normal}
html[data-style] .hero::after{display:none}

/* ===========================================================================
   LEDGER — 01-ledger.html
   Thesis: the money is the product; everything else is a supporting column.
   Graphite sheet, zero radius, rows that read as a statement. Up and down are
   the only colours that mean anything, so gold stops being the accent and
   green/red do the work.
   =========================================================================== */
/* KEYED ON data-look, NOT data-style, so a direction can WEAR this one's look
   without being it. `claudedesign` composes ledger's slots and renders the same
   .lg-* markup, so all 51 rules below have to reach it too - and duplicating 51
   selectors by hand is 51 chances to miss one. applyStyle() sets data-look from
   a direction's `look` property, falling back to its own key, so ledger still
   matches itself and nothing else changed. */
html[data-look="ledger"]{
  --void:#070809;
  /* THE NEUTRAL RAMP, from Josiah's Claude Design 1a THE LEDGER, taken from the
     artboard markup. The ground was already within two points of the artboard's
     #0B0B0B, so this is the "tightening" the brief promised - for THIS direction,
     which is the one the design is actually about. It is NOT in :root: the base
     palette is blue (--bg:#05101c) and warm greys on a cool ground read muddy.
     The cool neutrals it replaces (#F3F5F6 / #A8B0B7 / #949CA3) were a shade of
     grey away from arena, terminal, tolerance and position - six near-black
     directions converging - so warming only the designed one moves it APART from
     them rather than closer, which is the opposite of what applying one ramp to
     all six would have done. */
  /* FLAT SURFACES, and this is the artboard rather than a contrast workaround -
     the two happen to be the same answer.
     1a has NO panel fills anywhere. Its rows are flat black separated by
     hairlines, and it marks your own row with BOLD TYPE, not a raised
     background: screen 03 reads "=1 JOSIAH (YOU) 47.2 TIED" in bone against
     everyone else's grey. A statement is ruled, not tiled.
     It also resolves a real conflict. The dim tone clears AA on #0B0B0B at
     4.51:1 and on NOTHING lighter - measured across the whole ladder, #0D0D0C is
     already 4.46 - so with filled panels the 70 remaining failures could only
     have been fixed by lifting the dim tone to #8A847D, three points off the
     muted #8D8780, collapsing a three-step hierarchy into two. Flattening the
     surfaces keeps all three steps AND matches the design. */
  --bg:#0B0B0B; --bar:#0B0B0B; --panel:#0B0B0B; --panel2:#0B0B0B; --panel3:#141210;
  --line:#38342F; --line2:#26221E;
  /* --t3 IS A DELIBERATE DEVIATION FROM THE DESIGN, and it is measured.
     DESIGN-IMPLEMENT.md gives the dim tone as #6E6862 for "kickers, labels,
     timestamps" - all of which this app sets at 8-9px. On #0B0B0B that tone is
     3.58:1, and WCAG AA wants 4.5:1 for text that small. The contrast sweep found
     182 failures across eight ledger tabs, every one of them this colour at that
     size, with 467 elements measured and 0 skipped.
     #7E7871 is the SMALLEST lift that clears it: 4.51:1, measured with
     contrast.js rather than computed by hand. It keeps the warm R>G>B-by-6
     relationship the design's greys have, and the three-step hierarchy survives -
     ink #EFEAE3, muted #8D8780 at 5.54:1, dim #7E7871 at 4.51:1.
     The brief asked for exactly this check on exactly these tones, so acting on
     the result is the instruction, not a departure from it. */
  --t1:#EFEAE3; --t2:#8D8780; --t3:#7E7871;
  /* THE ACCENT IS DELIBERATELY UNCHANGED, and this is the interesting part.
     DESIGN-IMPLEMENT.md gives ledger the accent #FF4438 - and in the same
     paragraph states its colour argument: "red is reserved for LIABILITY - money
     you owe, days you missed, the overdue card. Anything you have earned is bone
     white."
     Those two cannot both be satisfied by renaming this token. --gold is the
     app's POSITIVE accent: it marks a lead, a win, a pot, a player of the week.
     Point it at #FF4438 and red starts celebrating things, which is precisely
     what the argument forbids. Implementing that argument means auditing where
     the accent is USED in this direction and removing it from everything that is
     not a liability - a screen-by-screen job, not a token swap. Recorded in
     HANDOFF.md rather than half-done here. */
  /* THE ACCENT IS BONE, NOT AMBER AND NOT RED. 1a's palette is bone, greys and
     red - there is no amber anywhere in it, and its CTA is a light bar with
     near-black type. The amber was the loudest thing on the rendered screen and
     the one colour the artboard does not contain.
     Bone rather than the spec's #FF4438 for the reason written above: --gold is
     the app's POSITIVE accent - it marks a lead, a pot, a player of the week - so
     pointing it at red would make red celebrate, which the direction forbids.
     Bone satisfies both halves of the argument at once. */
  --gold:#EFEAE3; --gold2:#DDD7CF; --onGold:#0B0B0B; --goldWash:#0B0B0B;
  /* The washes go flat too, for the same reason: they are surfaces that carry
     label text in the dim tone, and a tint is a raise. Kept as a hairline-tinted
     BORDER job instead - the artboard's own "CARRIED FORWARD" card is a red
     OUTLINE on black, not a red fill. */
  --red:#EF7E7E; --redFill:#9E2A2A; --redDot:#EF5E5E; --redWash:#0B0B0B;
  /* --green IS BONE IN THIS DIRECTION, and that is the argument applied at the
     lever that actually controls it. Fixing .lg-fig and .lg-v left green in eight
     more places - a 100% pay rate, a "+3" in the round-up, "Nobody takes it yet"
     - because those come from the shared --green token that every base screen
     uses for good news. This direction has no good-news colour: "anything you
     have earned is bone white", full stop. --onGreen stays dark for the rare
     case of type ON the fill. */
  --green:#EFEAE3; --onGreen:#0B0B0B; --greenWash:#0B0B0B;
  --blue:#6FA8D8;
  --disp:'IBM Plex Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,Roboto,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.32,.72,0,1);
  --d-fast:.14s; --d:.32s; --d-slow:.42s; --d-bar:.6s;
  /* A statement has no rounded corners. */
  --rad:0px; --radb:0px; --radt:2px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -24px 48px rgba(0,0,0,.7);
  --track:#141210; --press:#141210; --onRed:#fff;
  --scrim:rgba(6,6,6,.78); --fade:rgba(11,11,11,0);
  --hero:linear-gradient(180deg,#0B0B0B 0%,var(--bg) 100%);
}
/* THE FACE IS ALSO UNCHANGED, and also on purpose. The spec says "Archivo
   throughout" and this direction runs IBM Plex Sans, chosen for it because a
   statement reads like a statement. Swapping a typeface changes every line length
   on every screen, so it needs the geometry sweep re-run across the direction
   rather than a token edit - a separate job from the colour, and recorded as one. */
html[data-look="ledger"] .disp{font-weight:600;letter-spacing:-.015em}
html[data-look="ledger"] .d34{font-size:27px}
html[data-look="ledger"] .d46{font-size:36px}
html[data-look="ledger"] .k{font-weight:600;letter-spacing:.1em;font-family:var(--mono);font-size:10px}
html[data-look="ledger"] .wordmark{font-weight:600;letter-spacing:.08em;font-family:var(--mono)}
/* COMPOSITION: the hero is a statement header, not a title card — hairline
   rules above and below the figures, and the figures themselves set in mono at
   the size the name used to be. The money is the headline. */
html[data-look="ledger"] .hero{padding:14px 16px 0;border-bottom:1px solid var(--line)}
/* THE STRIP, AS 03 DRAWS IT: no box, no cell dividers, one rule above and one
   below, and the LABEL SITS OVER THE FIGURE - "STAKE EACH" then "$40.00", not
   the other way round. What shipped was the base component wearing a palette:
   a bordered three-cell box with vertical rules between the cells, which is the
   one thing at the top of the screen you cannot miss is different.

   column-reverse rather than reordered markup, because the DOM here is the base
   fixture screen's and shared by nine directions - the order is a fact about
   this direction's look, so it belongs in this direction's CSS. .l keeps a
   bottom margin because in column-reverse it is the box physically above .v. */
html[data-look="ledger"] .metarow{border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);margin-top:14px}
html[data-look="ledger"] .metacell{border-right:0;padding:11px 0 13px;
  display:flex;flex-direction:column-reverse;justify-content:flex-end}
html[data-look="ledger"] .metacell .v{font-size:21px;font-weight:500;margin:0}
html[data-look="ledger"] .metacell .l{font-weight:700;letter-spacing:.12em;font-size:9px;
  margin:0 0 6px;color:var(--t3)}
/* The title is set in caps on every artboard in this direction. */
html[data-look="ledger"] .hero h1.disp{text-transform:uppercase;letter-spacing:-.005em}
/* ---- 01 THE INVITE ------------------------------------------------------
   The proposal headline is caps here too - it is the same object as a fixture
   title, one screen earlier, and 01 draws it that way. Squared corners and a
   flat ground on the slip, for the reason the rest of this direction has them:
   a statement is ruled, not tiled. */
html[data-look="ledger"] .gate h1.disp{text-transform:uppercase;letter-spacing:-.005em;line-height:1.06}
html[data-look="ledger"] .rc-slip{border-width:1px 0;border-radius:0;background:none;
  margin-left:-16px;margin-right:-16px;padding:16px}
html[data-look="ledger"] .expo-bar{height:62px}
html[data-look="ledger"] .expo-lose b,
html[data-look="ledger"] .expo-win b{font-size:16px}
/* NO PROGRESS BAR. The direction's motion rule is "nothing moves except money",
   and this bar is a second rendering of the DAY cell three lines above it - the
   figure is already there in words, so nothing is lost by dropping the picture
   of it. 03 draws the strip and then goes straight to the table. */
html[data-look="ledger"] .hero .prog{display:none}
html[data-look="ledger"] .card{border-width:1px 0;border-radius:0;margin-left:-16px;margin-right:-16px;padding:14px 16px}
html[data-look="ledger"] .rowbtn{border-width:0 0 1px;border-radius:0;margin-left:-16px;margin-right:-16px;padding:12px 16px;background:none}
html[data-look="ledger"] .trow,
html[data-look="ledger"] .lbr{border-top-color:var(--line2)}
html[data-look="ledger"] .trow .pts,
html[data-look="ledger"] .lbr .tot{font-weight:500}
html[data-look="ledger"] .sect{margin:26px 0 9px}
html[data-look="ledger"] .sect .ln{background:var(--line)}

/* ===========================================================================
   VOLT — redo/A-volt.html, one of the three Josiah chose between on 2026-09-14.
   Thesis: today is a job with a number on it. Do the number.

   TWO ACCENTS AND NO THIRD. The prototype's :root carries exactly --volt and
   --hot, and its own sentence says why: "the work is volt yellow and the money
   you stand to lose is not." So --gold becomes volt, --red becomes hot, and
   --green does NOT become a third hue — earned things go bone, which is the
   same rule HEAT settles on. A palette that invents a green here would be
   arguing with the direction's one idea.

   MEASURED ON THIS GROUND, not carried over from the prototype's comments:
     #F4F5F2 ink   18.21    #D8FF47 volt  17.38    #838A7F dim   5.61
     #B9BFB3 mid   10.60    #FF4A2B hot    5.95    dim on panel  5.24
   Ink on volt and ink on hot are the same numbers inverted, which is why both
   accents take ink rather than the ground.

   NO MONO, and that is the direction rather than an omission: the prototype is
   Archivo alone with the WIDTH AXIS doing the work two families usually do.
   obligation already does this below and the .mono override is copied from it,
   because dropping --mono without it would set the money columns in a
   proportional face and lose the column.
   =========================================================================== */
html[data-style="volt"]{
  --void:#040506;
  --bg:#08090A; --bar:#0D0F11; --panel:#111315; --panel2:#171A1C; --panel3:#1E2226;
  --line:#333A3D; --line2:#23282B;
  --t1:#F4F5F2; --t2:#B9BFB3; --t3:#838A7F;          /* 18.21 / 10.60 / 5.61 */
  --gold:#D8FF47; --gold2:#BFE33A; --onGold:#08090A; --goldWash:#1B2109;
  --red:#FF4A2B; --redFill:#FF4A2B; --redDot:#FF4A2B; --redWash:#2A0F08;
  /* Bone, not green. See above. */
  --green:#F4F5F2; --onGreen:#08090A; --greenWash:#1A1C1A;
  --blue:#B9BFB3;
  --disp:'Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  --ease:cubic-bezier(.16,1.1,.3,1);                 /* the prototype's --snap */
  --d-fast:.10s; --d:.20s; --d-slow:.28s; --d-bar:.46s;
  --rad:10px; --radb:9px; --radt:3px; --rad2:8px; --radSheet:14px; --radPill:11px;
  --track:#171A1C; --press:#14181B; --onRed:#08090A;
  --scrim:rgba(4,5,6,.74); --fade:rgba(8,9,10,0);
  --shadow:0 -1px 0 var(--line2), 0 -20px 44px rgba(0,0,0,.66);
  --hero:linear-gradient(180deg,#121417 0%,#0C0E10 62%,var(--bg) 100%);
}
html[data-style="volt"] .mono{font-family:var(--disp);font-variant-numeric:tabular-nums}

/* ===========================================================================
   BOARD — redo/C-board.html, the third of the three.
   Thesis: a printed results board. Posted, accepted or rejected, in ink.

   THE ONLY LIGHT DIRECTION IN FRONT. light:true in styles.js sets
   html.style.colorScheme, which is what stops the browser painting dark form
   controls and scrollbars into a paper page.

   MEASURED:
     #12110F ink   16.72 on bone, 18.87 on paper     #006E3A green  5.65
     #5E5A52 mute   6.08 on bone,  6.86 on paper     #1B3DF0 blue   6.26
     #C41E00 red    5.27
   THE PROTOTYPE'S --redbig #E02400 IS DELIBERATELY NOT PORTED. It measures
   4.21 and the prototype guards it by hand with "24px+ ONLY". A token cannot
   carry that guard — every rule in the app can reach --red — so the one value
   that would need a size rule to be legal is the one value left behind.
   =========================================================================== */
html[data-style="board"]{
  --void:#DCD8CF;
  --bg:#F3F1EC; --bar:#EDEAE3; --panel:#FFFFFF; --panel2:#EDEAE3; --panel3:#E2DED5;
  --line:#9E998F; --line2:#C9C5BC;
  --t1:#12110F; --t2:#3B372F; --t3:#5E5A52;          /* 16.72 / 9.86 / 6.08 */
  /* Blue is YOU on this board, so it takes the accent slot the app reaches for
     when it wants to point at the person reading. */
  --gold:#1B3DF0; --gold2:#1631C6; --onGold:#FFFFFF; --goldWash:#E4E7FB;
  --red:#C41E00; --redFill:#C41E00; --redDot:#C41E00; --redWash:#F7E3DE;
  --green:#006E3A; --onGreen:#FFFFFF; --greenWash:#E0EDE5;
  --blue:#1B3DF0;
  --disp:'Familjen Grotesk','Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'Martian Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.2,.85,.2,1);                  /* the prototype's --flip */
  --d-fast:.11s; --d:.22s; --d-slow:.30s; --d-bar:.50s;
  /* Printed, so nothing is rounded except the sheet that slides over the page. */
  --rad:2px; --radb:2px; --radt:2px; --rad2:2px; --radSheet:2px; --radPill:2px;
  --track:#E2DED5; --press:#E8E4DC; --onRed:#FFFFFF;
  --scrim:rgba(30,28,24,.46); --fade:rgba(243,241,236,0);
  --shadow:0 -1px 0 var(--line2), 0 -18px 36px rgba(60,54,40,.18);
  --hero:linear-gradient(180deg,#FFFFFF 0%,#F8F6F1 70%,var(--bg) 100%);
}

/* ===========================================================================
   ARENA — 02-arena.html
   Thesis: a stadium scoreboard. Condensed caps at scoreboard size, volt on
   black, everything squared off and lit.
   =========================================================================== */
html[data-style="arena"]{
  --void:#05070A;
  --bg:#0A0D10; --bar:#0F1317; --panel:#12171B; --panel2:#191F25; --panel3:#232A31;
  --line:#2B333B; --line2:#20262C;
  --t1:#EEF2F5; --t2:#AEB8C0; --t3:#98A3AC;
  --gold:#D8FF3E; --gold2:#C7EE2E; --onGold:#0B1400; --goldWash:#161D06;
  --red:#FF9B8A; --redFill:#A52A1C; --redDot:#FF6B55; --redWash:#1B0F11;
  --green:#57E39B; --onGreen:#02160B; --greenWash:#0E1A14;
  --blue:#7CC4FF;
  --disp:'Barlow Condensed','Arial Narrow','Archivo',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.2,.9,.15,1);
  --d-fast:.1s; --d:.2s; --d-slow:.28s; --d-bar:.45s;
  --rad:3px; --radb:3px; --radt:2px;
  --rad2:3px; --radSheet:4px; --radPill:4px;
  --shadow:0 -16px 40px rgba(0,0,0,.75);
  --track:#1E252B; --press:#191F25; --onRed:#fff;
  --scrim:rgba(5,7,9,.8); --fade:rgba(10,13,16,0);
  --hero:linear-gradient(170deg,#182026 0%,#10161A 55%,var(--bg) 100%);
}
/* TYPE: Barlow Condensed is narrow enough to take 46px where Archivo took 34,
   which is the whole point of a scoreboard face. */
html[data-style="arena"] .disp{font-weight:700;letter-spacing:-.005em;text-transform:uppercase}
html[data-style="arena"] .d34{font-size:46px;line-height:.92}
html[data-style="arena"] .d28{font-size:38px;line-height:.94}
html[data-style="arena"] .d22{font-size:28px}
html[data-style="arena"] .d46{font-size:62px;line-height:.9}
html[data-style="arena"] .k{font-family:var(--disp);font-weight:700;font-size:12px;letter-spacing:.13em}
html[data-style="arena"] .wordmark{font-size:16px;letter-spacing:.1em;font-weight:700}
html[data-style="arena"] .btn{font-weight:700;font-size:16px;letter-spacing:.1em}
html[data-style="arena"] .tab span{font-size:10.5px;font-weight:700;letter-spacing:.06em}
/* COMPOSITION: the three meta figures become the scoreboard — volt, boxed, and
   the biggest thing on the screen after the name. */
html[data-style="arena"] .metarow{border-top:2px solid var(--gold);margin-top:14px;background:#0E1317}
html[data-style="arena"] .metacell{padding:11px 0 13px}
html[data-style="arena"] .metacell .v{font-family:var(--disp);font-size:30px;font-weight:700;color:var(--gold)}
html[data-style="arena"] .metacell .l{font-family:var(--disp);font-size:10.5px;letter-spacing:.1em;font-weight:600}
html[data-style="arena"] .trow{min-height:66px}
html[data-style="arena"] .trow .nm{font-size:21px;font-weight:700;text-transform:uppercase;letter-spacing:0}
html[data-style="arena"] .trow .pts{font-size:24px}
html[data-style="arena"] .lbr .nm{font-size:18px;font-weight:600;text-transform:uppercase}
html[data-style="arena"] .prog{height:6px;border-radius:0}
html[data-style="arena"] .prog i{border-radius:0}

/* ===========================================================================
   TERMINAL — 06-terminal.html
   Thesis: the crew is a system and you are reading its log. ONE face, mono,
   everywhere — including the display sizes, which is the uncomfortable part.
   Zero radius, amber as the only accent, 165ms.
   =========================================================================== */
html[data-style="terminal"]{
  --void:#050708;
  --bg:#0B0D0F; --bar:#07090B; --panel:#121518; --panel2:#161A1E; --panel3:#1E242A;
  --line:#262C32; --line2:#1A1F24;
  --t1:#E8EAED; --t2:#C2C9D0; --t3:#98A1A9;
  --gold:#FFB020; --gold2:#E09513; --onGold:#1C1205; --goldWash:#1C1A12;
  --red:#FF8C8C; --redFill:#A32020; --redDot:#FF5C5C; --redWash:#1E1011;
  --green:#35D07F; --onGreen:#02150A; --greenWash:#0B1D14;
  --blue:#5AC8E8;
  --disp:'IBM Plex Mono',ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  --ease:cubic-bezier(.2,.85,.25,1);
  --d-fast:.08s; --d:.165s; --d-slow:.22s; --d-bar:.3s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -20px 40px rgba(0,0,0,.8);
  --track:#161A1E; --press:#161A1E; --onRed:#fff;
  --scrim:rgba(4,6,7,.82); --fade:rgba(11,13,15,0);
  --hero:none;
}
html[data-style="terminal"] .disp{font-weight:600;letter-spacing:-.02em}
html[data-style="terminal"] .d34{font-size:25px}
html[data-style="terminal"] .d28{font-size:21px}
html[data-style="terminal"] .d22{font-size:18px}
html[data-style="terminal"] .d46{font-size:32px}
html[data-style="terminal"] .k{font-weight:500;letter-spacing:.08em;font-size:10px}
html[data-style="terminal"] .wordmark{font-weight:500;letter-spacing:.06em;font-size:12px}
html[data-style="terminal"] .wordmark::before{content:"$ ";color:var(--gold)}
html[data-style="terminal"] .btn{font-weight:600;font-size:12.5px;letter-spacing:.08em}
/* COMPOSITION: no hero. A header block with a rule under it, like a section of
   output — and the three figures become three key=value pairs on one line. */
html[data-style="terminal"] .hero{background:none;padding:12px 14px 0;border-bottom:1px solid var(--line)}
html[data-style="terminal"] .metarow{border-top:1px solid var(--line2);margin-top:11px}
html[data-style="terminal"] .metacell{padding:9px 0 10px;border-right:1px solid var(--line2)}
html[data-style="terminal"] .metacell .v{font-size:16px;font-weight:500}
html[data-style="terminal"] .metacell .l{font-weight:500;letter-spacing:.07em;font-size:9px}
html[data-style="terminal"] .metacell .l::before{content:"";}
html[data-style="terminal"] .card{border-radius:0}
html[data-style="terminal"] .rowbtn{border-radius:0}
html[data-style="terminal"] .sect .k::before{content:"── "}
html[data-style="terminal"] .sect .ln{display:none}
html[data-style="terminal"] .trow{min-height:54px}
html[data-style="terminal"] .trow .nm{font-size:14px;font-weight:500;letter-spacing:0}
html[data-style="terminal"] .prog{height:10px;border-radius:0;background:var(--panel2)}
html[data-style="terminal"] .prog i{border-radius:0}
html[data-style="terminal"] .av{border-radius:0}
html[data-style="terminal"] .tag{border-radius:0;letter-spacing:.08em;font-weight:600}

/* ===========================================================================
   RECEIPT — 09-receipt.html
   Thesis: a betting slip you can hold. Printed, not rendered. Cream stock,
   dotted perforations doing all the dividing, one ink and one red stamp.
   First of the four light styles.
   =========================================================================== */
html[data-style="receipt"]{
  --void:#ddd6c0;
  --bg:#f0ecdf; --bar:#e6e1d0; --panel:#fffdf6; --panel2:#e9e4d2; --panel3:#ded8c3;
  --line:#c9c0a8; --line2:#d6cdb6;
  --t1:#141309; --t2:#3d3826; --t3:#57503c;
  --gold:#7a5a10; --gold2:#63490b; --onGold:#fffdf6; --goldWash:#eae2c8;
  --red:#9e2b25; --redFill:#9e2b25; --redDot:#9e2b25; --redWash:#f2e0dd;
  --green:#1f5c36; --onGreen:#fffdf6; --greenWash:#e2ece3;
  --blue:#1f3a6e;
  --disp:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.22,.9,.24,1);
  --d-fast:.16s; --d:.42s; --d-slow:.52s; --d-bar:.62s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -2px 0 var(--line), 0 -18px 36px rgba(80,70,40,.2);
  --track:#ded8c3; --press:#e4dfcd; --onRed:#fffdf6;
  --scrim:rgba(40,36,22,.5); --fade:rgba(240,236,223,0);
  --hero:linear-gradient(180deg,#fffdf6 0%,#faf6ea 70%,var(--bg) 100%);
}
html[data-style="receipt"] .disp{font-weight:600;letter-spacing:-.01em}
html[data-style="receipt"] .d34{font-size:24px}
html[data-style="receipt"] .d28{font-size:20px}
html[data-style="receipt"] .d22{font-size:17px}
html[data-style="receipt"] .d46{font-size:30px}
html[data-style="receipt"] .k{font-weight:600;letter-spacing:.14em;font-size:9.5px}
html[data-style="receipt"] .wordmark{font-weight:600;letter-spacing:.2em;font-size:12px}
html[data-style="receipt"] .btn{font-weight:600;font-size:12.5px;letter-spacing:.12em}
/* SURFACE: perforations. Every divider in the app becomes a dotted rule, which
   is the one thing that makes a screen read as printed stock rather than as a
   light theme. Done with border-style rather than an image so it survives any
   colour change. */
html[data-style="receipt"] .hero{border-bottom:1px dashed var(--line)}
html[data-style="receipt"] .metarow{border-top:1px dashed var(--line)}
html[data-style="receipt"] .metacell{border-right:1px dashed var(--line2)}
html[data-style="receipt"] .metacell .v{font-size:18px;font-weight:600}
html[data-style="receipt"] .card{border:1px dashed var(--line);background:var(--panel)}
html[data-style="receipt"] .rowbtn{border:1px dashed var(--line);background:var(--panel)}
html[data-style="receipt"] .trow,
html[data-style="receipt"] .lbr{border-top:1px dashed var(--line2)}
html[data-style="receipt"] .trow:last-child{border-bottom:1px dashed var(--line2)}
html[data-style="receipt"] .lbr{border-bottom:1px dashed var(--line2);border-top:0}
html[data-style="receipt"] .sect .ln{background:none;border-top:1px dashed var(--line);height:0}
html[data-style="receipt"] .av{border-radius:0}
html[data-style="receipt"] .tag.hollow{border-style:dashed}
html[data-style="receipt"] #chan{border-bottom:1px dashed var(--line)}
html[data-style="receipt"] #tabs{border-top:1px dashed var(--line)}
html[data-style="receipt"] .prog{background:var(--track);border:1px dashed var(--line);height:8px}

/* ===========================================================================
   TOLERANCE — 14-tolerance.html
   Thesis: every number is a measurement, and the app never shows one without
   showing how it was obtained. Graphite, hairlines over fills, no cards
   anywhere, ONE chromatic accent, and a mechanical curve with late
   acceleration and no overshoot.
   =========================================================================== */
html[data-style="tolerance"]{
  --void:#060708;
  --bg:#0B0D0E; --bar:#0B0D0E; --panel:#121517; --panel2:#191D20; --panel3:#22282B;
  --line:rgba(255,255,255,.20); --line2:rgba(255,255,255,.10);
  --t1:#F4F6F7; --t2:#C9CFD3; --t3:#9AA2A7;
  --gold:#E8A33D; --gold2:#CC8A28; --onGold:#140D02; --goldWash:#1A1408;
  --red:#E8A33D; --redFill:#7A4A12; --redDot:#E8A33D; --redWash:#16110A;
  --green:#C9CFD3; --onGreen:#0B0D0E; --greenWash:#15191B;
  --blue:#C9CFD3;
  --disp:'IBM Plex Sans Condensed','Roboto Condensed','Helvetica Neue',Arial,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.45,.02,.09,.98);
  --d-fast:.15s; --d:.3s; --d-slow:.4s; --d-bar:.6s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -20px 44px rgba(0,0,0,.7);
  --track:#191D20; --press:#191D20; --onRed:#fff;
  --scrim:rgba(5,6,7,.8); --fade:rgba(11,13,14,0);
  --hero:none;
}
/* The single chromatic accent is a RULE: green and blue are neutralised above,
   so a figure that is coloured is a figure the app is flagging. */
html[data-style="tolerance"] .disp{font-weight:600;letter-spacing:-.01em}
html[data-style="tolerance"] .d34{font-size:31px}
html[data-style="tolerance"] .k{font-weight:600;letter-spacing:.11em;font-size:10px;font-family:var(--mono)}
html[data-style="tolerance"] .wordmark{font-weight:600;letter-spacing:.1em;font-family:var(--mono);font-size:12px}
html[data-style="tolerance"] .btn{font-weight:600;font-size:13px;letter-spacing:.1em}
/* COMPOSITION: edge-to-edge. No cards, no insets — every block runs the full
   width and is separated by a hairline, so the page reads as an instrument
   index rather than a stack of objects. */
html[data-style="tolerance"] .hero{background:none;padding:14px 20px 0;border-bottom:1px solid var(--line)}
html[data-style="tolerance"] .pad{padding:0 20px}
html[data-style="tolerance"] .card{background:none;border:0;border-top:1px solid var(--line2);
  border-radius:0;margin:0 -20px;padding:14px 20px}
html[data-style="tolerance"] .rowbtn{background:none;border:0;border-bottom:1px solid var(--line2);
  border-radius:0;margin:0 -20px;padding:13px 20px}
html[data-style="tolerance"] .metarow{border-top:1px solid var(--line2);margin-top:13px}
html[data-style="tolerance"] .metacell{border-right:1px solid var(--line2);padding:11px 0 12px}
html[data-style="tolerance"] .metacell .v{font-size:19px;font-weight:400}
html[data-style="tolerance"] .metacell .l{font-weight:600;letter-spacing:.1em;font-size:9px}
html[data-style="tolerance"] .sect{margin:24px 0 8px}
html[data-style="tolerance"] .sect .ln{background:var(--line2)}
html[data-style="tolerance"] .trow.me,
html[data-style="tolerance"] .lbr.me{background:none;box-shadow:inset 2px 0 0 var(--gold)}
html[data-style="tolerance"] .av{border-radius:0}
html[data-style="tolerance"] .prog{border-radius:0;height:2px}
html[data-style="tolerance"] .prog i{border-radius:0}
html[data-style="tolerance"] .tag{border-radius:0;font-weight:600;letter-spacing:.09em}
/* Navigation is a dense index, not a menu. */
html[data-style="tolerance"] #tabs{height:52px}
html[data-style="tolerance"] .tab span{font-size:9px;letter-spacing:.1em;font-weight:600}
html[data-style="tolerance"] .tab i{height:2px;left:0;right:0}

/* ===========================================================================
   POSITION — 15-position.html
   Thesis: it is called Sweat EQUITY. You hold a position and it has a price.
   Near-black, hierarchy from luminance only — surfaces are stacked white
   alphas, not hues — and 120ms, because fast is a choice.
   =========================================================================== */
html[data-style="position"]{
  --void:#050506;
  --bg:#0A0A0B; --bar:#0A0A0B; --panel:rgba(255,255,255,.030); --panel2:rgba(255,255,255,.060);
  --panel3:rgba(255,255,255,.10);
  --line:rgba(255,255,255,.17); --line2:rgba(255,255,255,.085);
  --t1:#F5F5F7; --t2:#A6A6AE; --t3:#8C8C95;
  --gold:#8AA9FF; --gold2:#6E8FEE; --onGold:#05070F; --goldWash:rgba(138,169,255,.09);
  --red:#FF7A7A; --redFill:#8E2222; --redDot:#FF5C5C; --redWash:rgba(255,122,122,.08);
  --green:#5BD99A; --onGreen:#04140B; --greenWash:rgba(91,217,154,.08);
  --blue:#8AA9FF;
  --disp:'Space Grotesk','Helvetica Neue',Arial,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.2,.8,.2,1);
  /* Asymmetric on purpose: summon instant, dismiss a touch slower. */
  --d-fast:.06s; --d:.12s; --d-slow:.15s; --d-bar:.3s;
  --rad:8px; --radb:8px; --radt:3px;
  --rad2:8px; --radSheet:14px; --radPill:14px;
  --shadow:0 -12px 30px rgba(0,0,0,.7);
  --track:rgba(255,255,255,.06); --press:rgba(255,255,255,.06); --onRed:#fff;
  --scrim:rgba(5,5,6,.74); --fade:rgba(10,10,11,0);
  --hero:none;
}
html[data-style="position"] .disp{font-weight:600;letter-spacing:-.03em}
html[data-style="position"] .d34{font-size:30px}
html[data-style="position"] .d22{font-size:19px}
html[data-style="position"] .k{font-weight:500;letter-spacing:.09em;font-size:9.5px;font-family:var(--mono)}
html[data-style="position"] .wordmark{font-weight:600;letter-spacing:-.02em;font-size:14px;text-transform:none}
html[data-style="position"] .btn{font-weight:600;font-size:13px;letter-spacing:.01em;text-transform:none}
/* COMPOSITION: no hero ground at all, and the three figures become a price
   strip — mono, right-aligned, tight. A book, not a banner. */
html[data-style="position"] .hero{background:none;padding:14px 18px 0;border-bottom:1px solid var(--line2)}
html[data-style="position"] .metarow{border-top:1px solid var(--line2);margin-top:12px}
html[data-style="position"] .metacell{border-right:1px solid var(--line2);padding:10px 0 11px}
html[data-style="position"] .metacell .v{font-size:18px;font-weight:400;letter-spacing:-.02em}
html[data-style="position"] .metacell .l{font-weight:500;letter-spacing:.08em;font-size:8.5px}
html[data-style="position"] .card{background:var(--panel);border-color:var(--line2)}
html[data-style="position"] .rowbtn{background:var(--panel);border-color:var(--line2)}
html[data-style="position"] .trow{min-height:56px}
html[data-style="position"] .trow .nm{font-size:15px;font-weight:500;letter-spacing:-.02em}
html[data-style="position"] .trow .pts{font-size:19px;font-weight:400;letter-spacing:-.03em}
html[data-style="position"] .sect .ln{background:var(--line2)}
html[data-style="position"] .tab span{text-transform:none;letter-spacing:0;font-size:10px;font-weight:500}

/* ===========================================================================
   THE MONTH — 16-the-month.html
   Thesis: the unit is the day, not the challenge. Paper ground, one black ink,
   one vermilion used as a MARK and never as a fill. Swiss specimen: hard grid,
   very large headings, everything else small.
   =========================================================================== */
html[data-style="month"]{
  --void:#E3E0D8;
  --bg:#F2F0EB; --bar:#E8E5DE; --panel:#FAF9F6; --panel2:#E8E5DE; --panel3:#DDD9D1;
  --line:#A9A49A; --line2:#D3CFC6;
  --t1:#141210; --t2:#45413B; --t3:#575249;   /* 4.45:1 at #5F5B54 — measured, not guessed */
  /* Direction 16's vermilion is #C0341B and it is a MARK, never a fill — which
     means it is ink, and ink has to clear 4.5:1. Measured at 4.45:1 on --bar
     across 14 elements, so the ink form is deepened to 5.5:1 on --bar and
     4.96:1 on --panel3 while --red keeps the original for the LIVE fill, which
     carries --onRed rather than being read as text. */
  /* 1c THE GRID's COLOUR ARGUMENT, and it required taking red OFF the accent.
     The argument: "bone white is a filled square; RED MEANS A BREAK - a blank
     day, a dropped streak, an unpaid debt. Red never celebrates anything here,
     so a red mark on the grid reads as damage at a glance."
     --gold was #A82A14, a deep vermilion, because direction 16's palette used
     vermilion as its mark. Measured on the running app, that made red mark:
     "double" on a doubled fixture, a points total of 12, deltas of +12/+10/+9,
     your position, and the live-fixture counts. RED WAS CELEBRATING EVERYTHING -
     while --red, two shades away, marked a missed day. One hue meaning both
     "points!" and "you lost a day" is precisely the ambiguity this argument
     exists to remove, and it cannot be fixed while the positive accent IS the
     damage colour.
     So the accent is the ink. In a light direction the filled square is ink, so
     an ink accent and an ink-filled square are the same statement. Red is left
     to --red alone, which is what the breaks use. */
  --gold:#141210; --gold2:#2A2620; --onGold:#F2F0EB; --goldWash:#E6E3DC;
  --red:#C0341B; --redFill:#C0341B; --redDot:#C0341B; --redWash:#F4E3DF;
  /* No good-news hue, same as ledger: the 16 green "alive" marks were a colour
     that congratulates, in a direction whose only colour statement is damage. */
  --green:#141210; --onGreen:#F2F0EB; --greenWash:#E6E3DC;
  --blue:#1F3A6E;
  --disp:'Schibsted Grotesk','Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'DM Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.455,.03,.515,.955);
  --d-fast:.15s; --d:.3s; --d-slow:.4s; --d-bar:.62s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -18px 40px rgba(60,55,45,.22);
  --track:#DDD9D1; --press:#E8E5DE; --onRed:#FAF9F6;
  --scrim:rgba(35,32,28,.52); --fade:rgba(242,240,235,0);
  --hero:none;
}
/* TYPE: set very large, and the curve is applied to almost nothing. */
html[data-style="month"] .disp{font-weight:700;letter-spacing:-.035em}
html[data-style="month"] .d34{font-size:40px;line-height:.96}
html[data-style="month"] .d28{font-size:32px}
html[data-style="month"] .d22{font-size:24px}
html[data-style="month"] .d46{font-size:54px;line-height:.94}
html[data-style="month"] .k{font-family:var(--mono);font-weight:400;letter-spacing:.06em;font-size:10px}
html[data-style="month"] .p{color:var(--t2)}
html[data-style="month"] .wordmark{font-weight:700;letter-spacing:-.02em;font-size:14px}
html[data-style="month"] .btn{font-weight:600;font-size:13px;letter-spacing:.04em}
/* COMPOSITION: a label rail. The hero's kicker row becomes a caption line above
   a very large heading, and the three-figure strip is dropped in favour of the
   grid that the signature puts underneath it. */
html[data-style="month"] .hero{background:none;padding:16px 20px 0;border-bottom:1px solid var(--line)}
html[data-style="month"] .pad{padding:0 20px}
html[data-style="month"] .metarow{border-top:1px solid var(--line);margin-top:14px}
html[data-style="month"] .metacell{border-right:1px solid var(--line2);padding:11px 0 13px}
html[data-style="month"] .metacell .v{font-family:var(--disp);font-size:26px;font-weight:700;letter-spacing:-.03em}
html[data-style="month"] .metacell .l{font-family:var(--mono);font-weight:400;letter-spacing:.05em;font-size:9px}
html[data-style="month"] .card{border-radius:0;background:none;border:1px solid var(--line2);padding:14px}
html[data-style="month"] .rowbtn{border-radius:0;background:none;border:0;border-bottom:1px solid var(--line2);
  margin:0 -20px;padding:13px 20px}
html[data-style="month"] .sect .ln{background:var(--line2)}
html[data-style="month"] .trow,
html[data-style="month"] .lbr{border-top-color:var(--line2)}
html[data-style="month"] .trow .nm{font-size:17px;font-weight:700;letter-spacing:-.02em}
html[data-style="month"] .trow .pts{font-family:var(--disp);font-size:22px;font-weight:700;letter-spacing:-.03em}
html[data-style="month"] .prog{height:3px;border-radius:0;background:var(--track)}
html[data-style="month"] .prog i{border-radius:0}
html[data-style="month"] .av{border-radius:0}
/* Vermilion is a MARK. It never fills a button, so the primary action is ink. */
html[data-style="month"] .btn.primary{background:var(--t1);color:#FAF9F6}
html[data-style="month"] .tag.gold{background:none;color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}

/* ===========================================================================
   OBLIGATION — 17-obligation.html
   Thesis: a ledger of trust between friends; the leaderboard is a side effect.
   Editorial. Newsreader with its true italic load-bearing, hairline rules doing
   all the dividing, no fills, no cards, measure near 65 characters, 520ms.
   =========================================================================== */
html[data-style="obligation"]{
  --void:#EFEBE2;
  --bg:#FBF9F4; --bar:#FBF9F4; --panel:#F6F3EC; --panel2:#F1EDE4; --panel3:#E7E2D6;
  --line:#B8B1A4; --line2:#DDD8CE;
  --t1:#1A1714; --t2:#4A453F; --t3:#635D55;
  --gold:#8C2F1F; --gold2:#722618; --onGold:#FBF9F4; --goldWash:#F3E6E2;
  --red:#8C2F1F; --redFill:#8C2F1F; --redDot:#8C2F1F; --redWash:#F3E6E2;
  --green:#2A5438; --onGreen:#FBF9F4; --greenWash:#E6EDE7;
  --blue:#274A73;
  --disp:'Newsreader',Georgia,'Times New Roman',serif;
  --mono:'Public Sans','Helvetica Neue',Arial,sans-serif;
  --ease:cubic-bezier(.23,1,.32,1);
  --d-fast:.2s; --d:.52s; --d-slow:.62s; --d-bar:.8s;
  --rad:0px; --radb:2px; --radt:2px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -16px 36px rgba(70,60,48,.18);
  --track:#E7E2D6; --press:#F1EDE4; --onRed:#FBF9F4;
  --scrim:rgba(40,34,28,.48); --fade:rgba(251,249,244,0);
  --hero:none;
}
/* No mono: numbers are set in the text face's own tabular figures. --mono is
   Public Sans, used for controls only, which is why labels look sans and
   everything else looks set. */
html[data-style="obligation"] .disp{font-weight:600;letter-spacing:-.012em}
html[data-style="obligation"] .d34{font-size:33px;line-height:1.08}
html[data-style="obligation"] .d28{font-size:27px;line-height:1.1}
html[data-style="obligation"] .d22{font-size:22px;line-height:1.14}
html[data-style="obligation"] .d46{font-size:42px;line-height:1.04}
html[data-style="obligation"] .k{font-family:var(--mono);font-weight:600;letter-spacing:.11em;font-size:9.5px}
html[data-style="obligation"] .p{font-family:var(--disp);font-size:15.5px;line-height:1.58;max-width:34em}
html[data-style="obligation"] .p.sm{font-size:14px;line-height:1.5}
html[data-style="obligation"] .mono{font-family:var(--disp);font-variant-numeric:tabular-nums}
html[data-style="obligation"] .wordmark{font-family:var(--disp);font-weight:600;letter-spacing:-.01em;
  font-size:16px;text-transform:none}
html[data-style="obligation"] .btn{font-family:var(--mono);font-weight:600;font-size:12.5px;letter-spacing:.08em}
/* COMPOSITION: hairlines only. Nothing is filled, nothing is a card, and the
   three-figure strip stacks into a list because a 65-character measure has no
   room for three columns of anything. */
html[data-style="obligation"] .hero{background:none;padding:18px 22px 0;border-bottom:1px solid var(--line)}
html[data-style="obligation"] .pad{padding:0 22px}
html[data-style="obligation"] .metarow{flex-direction:column;border-top:1px solid var(--line2);margin-top:14px}
html[data-style="obligation"] .metacell{display:flex;align-items:baseline;justify-content:space-between;
  border-right:0;border-bottom:1px solid var(--line2);padding:9px 0}
html[data-style="obligation"] .metacell:last-child{border-bottom:0}
html[data-style="obligation"] .metacell .v{font-family:var(--disp);font-size:21px;font-weight:600;order:2}
html[data-style="obligation"] .metacell .l{margin-top:0;font-weight:600;letter-spacing:.1em;font-size:9.5px;order:1}
html[data-style="obligation"] .card{background:none;border:0;border-top:1px solid var(--line2);
  border-radius:0;margin:0;padding:13px 0}
html[data-style="obligation"] .rowbtn{background:none;border:0;border-bottom:1px solid var(--line2);
  border-radius:0;margin:0;padding:14px 0}
html[data-style="obligation"] .sect{margin:28px 0 10px}
html[data-style="obligation"] .sect .ln{background:var(--line2)}
html[data-style="obligation"] .trow,
html[data-style="obligation"] .lbr{border-top-color:var(--line2);font-family:var(--disp)}
html[data-style="obligation"] .trow .nm{font-size:18px;font-weight:600;letter-spacing:-.012em}
html[data-style="obligation"] .trow .pts{font-family:var(--disp);font-size:21px;font-weight:600}
html[data-style="obligation"] .trow.me{background:none;box-shadow:inset 2px 0 0 var(--gold)}
html[data-style="obligation"] .av{border-radius:50%}
html[data-style="obligation"] .prog{height:2px;border-radius:0;background:var(--track)}
html[data-style="obligation"] .prog i{border-radius:0}
html[data-style="obligation"] .tab{font-family:var(--mono)}
html[data-style="obligation"] .tab span{font-size:9.5px;letter-spacing:.08em}

/* ===========================================================================
   RESTRAINT — 18-restraint.html
   Thesis: the app says almost nothing. One number and one verb per screen.
   Two neutrals, enormous space, exactly one relief effect (a hairline), and
   800ms, because slow reads as weight. This is the direct answer to
   Broadcast's density.
   =========================================================================== */
html[data-style="restraint"]{
  --void:#DEDBD3;
  --bg:#E9E6DF; --bar:#E9E6DF; --panel:#E9E6DF; --panel2:#E3E0D8; --panel3:#DCD8CE;
  --line:#C6C2B8; --line2:#D4D0C6;
  --t1:#1C1B18; --t2:#4C4A43; --t3:#5A574F;
  --gold:#1C1B18; --gold2:#1C1B18; --onGold:#E9E6DF; --goldWash:#E0DDD4;
  --red:#6B2A20; --redFill:#6B2A20; --redDot:#6B2A20; --redWash:#E5DCD6;
  --green:#2B4A33; --onGreen:#E9E6DF; --greenWash:#DEE3DC;
  --blue:#2B3C54;
  --disp:'Instrument Serif',Georgia,'Times New Roman',serif;
  --mono:'Hanken Grotesk','Helvetica Neue',Arial,sans-serif;
  --ease:cubic-bezier(.445,.05,.55,.95);
  --d-fast:.3s; --d:.8s; --d-slow:.9s; --d-bar:1.1s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line);
  --track:#DCD8CE; --press:#E3E0D8; --onRed:#E9E6DF;
  --scrim:rgba(35,33,28,.42); --fade:rgba(233,230,223,0);
  --hero:none;
}
/* Two faces, one voice: Instrument Serif for the single enormous figure,
   Hanken Grotesk for chrome. Nothing else. */
html[data-style="restraint"] .disp{font-weight:400;letter-spacing:-.02em}
html[data-style="restraint"] .d34{font-size:44px;line-height:1.04}
html[data-style="restraint"] .d28{font-size:36px;line-height:1.06}
html[data-style="restraint"] .d22{font-size:28px;line-height:1.1}
html[data-style="restraint"] .d46{font-size:58px;line-height:1}
html[data-style="restraint"] .k{font-family:var(--mono);font-weight:600;letter-spacing:.14em;font-size:9.5px}
html[data-style="restraint"] .p{font-family:var(--mono);font-size:14.5px;line-height:1.62;max-width:32em}
html[data-style="restraint"] .p.sm{font-size:13px}
html[data-style="restraint"] .mono{font-family:var(--mono)}
html[data-style="restraint"] .wordmark{font-family:var(--disp);font-weight:400;letter-spacing:.02em;
  font-size:17px;text-transform:none}
html[data-style="restraint"] .wordmark b{color:var(--t1)}
html[data-style="restraint"] .btn{font-family:var(--mono);font-weight:600;font-size:12.5px;letter-spacing:.1em}
/* COMPOSITION: enormous space. Three times the padding, sections with no rule,
   and the figure strip becomes one stacked list with air between the items —
   because showing three things at once is the thing this direction refuses. */
html[data-style="restraint"] .hero{background:none;padding:34px 26px 0;border-bottom:0}
html[data-style="restraint"] .pad{padding:0 26px}
html[data-style="restraint"] .metarow{flex-direction:column;border-top:0;margin-top:30px;gap:22px}
html[data-style="restraint"] .metacell{border-right:0;padding:0}
html[data-style="restraint"] .metacell .v{font-family:var(--disp);font-size:40px;font-weight:400;line-height:1}
html[data-style="restraint"] .metacell .l{margin-top:7px;letter-spacing:.14em;font-size:9.5px}
html[data-style="restraint"] .card{background:none;border:0;border-top:1px solid var(--line);
  border-radius:0;padding:20px 0}
html[data-style="restraint"] .rowbtn{background:none;border:0;border-top:1px solid var(--line2);
  border-radius:0;padding:20px 0;min-height:68px}
html[data-style="restraint"] .sect{margin:44px 0 16px}
html[data-style="restraint"] .sect .ln{display:none}
html[data-style="restraint"] .trow{min-height:72px;border-top-color:var(--line2);padding:14px 0}
html[data-style="restraint"] .trow .nm{font-family:var(--disp);font-size:22px;font-weight:400;letter-spacing:-.01em}
html[data-style="restraint"] .trow .pts{font-family:var(--disp);font-size:26px;font-weight:400}
html[data-style="restraint"] .trow.me{background:none;box-shadow:inset 2px 0 0 var(--t1)}
html[data-style="restraint"] .lbr{border-bottom-color:var(--line2);min-height:62px}
html[data-style="restraint"] .prog{height:1px;border-radius:0;background:var(--line2)}
html[data-style="restraint"] .prog i{border-radius:0}
html[data-style="restraint"] .tab{font-family:var(--mono)}
html[data-style="restraint"] .tab span{font-size:9px;letter-spacing:.13em}
html[data-style="restraint"] .tab i{height:1px}
html[data-style="restraint"] .tag{font-family:var(--mono);font-weight:600;letter-spacing:.1em}

/* ===========================================================================
   RIVALRY — 19-rivalry.html
   Thesis: not a leaderboard, a series of individual grudges. Invariant black
   chrome plus a per-rival colour FIELD that skins the whole screen. --skin is
   set on the root by applyRival() in app.js from the person the day picked, so
   the accent in this style is a human being.
   =========================================================================== */
html[data-look="rivalry"]{
  --void:#050505;
  /* The fallback matters: --skin is supplied by script, and a crew of one has
     no rival, so the style has to look deliberate with no skin at all. */
  --skin:#FF5C38;
  --bg:#0B0B0B; --bar:#0B0B0B; --panel:rgba(255,255,255,.045); --panel2:rgba(255,255,255,.08);
  --panel3:rgba(255,255,255,.13);
  --line:rgba(255,255,255,.16); --line2:rgba(255,255,255,.09);
  --t1:#FFFFFF; --t2:#A8A8A8; --t3:#8E8E8E;
  /* The INK form of the skin. A member colour is a mid-saturation hue chosen to
     be told apart on an avatar, not to be read as 9px type on black — the raw
     skin measured 3.84:1 across 49 elements. Lightened in oklab so hue survives
     and only lightness moves. --skin itself stays raw for fills and the field. */
  --skinInk:color-mix(in oklab, var(--skin) 62%, #FFFFFF);
  /* THE ACCENT IS RED, AND IT IS FIXED. It used to be var(--skinInk) - the
     day's RIVAL's colour - so every rule, button, active tab and section mark
     in the app changed hue daily depending on who got picked. Josiah saw it
     red and liked it; the coordinator saw it teal (#0e7c66) an hour later,
     because the rival had changed. An app whose whole accent is a lottery
     does not read as one product.
     Measured 5.75:1 on --bg #0B0B0B, which clears AA for BODY text and not
     merely for headlines. The rival's own colour stays as --skin and keeps
     the jobs that are genuinely about that person: the hero's diagonal field,
     their name, and the gap when you are behind them. The mechanism survives;
     the brand stops moving. */
  --gold:#FF4438; --gold2:#E8382B; --onGold:#0B0B0B; --goldWash:rgba(255,68,56,.12);
  --red:#FF7060; --redFill:#8E2A18; --redDot:var(--gold); --redWash:rgba(255,68,56,.08);
  --green:#7BE0A4; --onGreen:#071409; --greenWash:rgba(255,255,255,.05);
  --blue:#8FB6FF;
  --disp:'Bricolage Grotesque','Helvetica Neue',Arial,sans-serif;
  --mono:'Martian Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.365,.305,0,1);
  --d-fast:.13s; --d:.26s; --d-slow:.34s; --d-bar:.52s;
  --rad:0px; --radb:0px; --radt:0px;
  --rad2:0px; --radSheet:0px; --radPill:0px;
  --shadow:0 -1px 0 var(--line), 0 -20px 44px rgba(0,0,0,.8);
  --track:rgba(255,255,255,.10); --press:rgba(255,255,255,.08); --onRed:#fff;
  --scrim:rgba(5,5,5,.8); --fade:rgba(11,11,11,0);
  /* THE COLOUR FIELD. The screen itself wears the rival, which is the part no
     other direction does — and it drains to black when you are ahead, handled
     by [data-beat] below. */
  --hero:linear-gradient(168deg,color-mix(in oklab,var(--skin) 26%,#0B0B0B) 0%,
                                color-mix(in oklab,var(--skin) 9%,#0B0B0B) 58%,var(--bg) 100%);
}
/* Width and optical-size axes load-bearing: headings ride wide, labels ride
   narrow, which is the whole reason this face was chosen. */
html[data-look="rivalry"] .disp{font-weight:800;font-stretch:100%;letter-spacing:-.035em}
html[data-look="rivalry"] .d34{font-size:36px;line-height:.98}
html[data-look="rivalry"] .d28{font-size:29px}
html[data-look="rivalry"] .d22{font-size:23px}
html[data-look="rivalry"] .d46{font-size:48px;line-height:.96}
html[data-look="rivalry"] .k{font-family:var(--mono);font-weight:400;letter-spacing:.02em;font-size:9px}
html[data-look="rivalry"] .wordmark{font-weight:800;font-stretch:75%;letter-spacing:-.01em;font-size:15px}
html[data-look="rivalry"] .wordmark b{color:var(--gold)}   /* ink, not field: 15px type */
html[data-look="rivalry"] .btn{font-weight:800;font-size:13px;letter-spacing:-.01em;text-transform:none}
html[data-look="rivalry"] .hero{padding:16px 20px 0;border-bottom:1px solid var(--line2)}
html[data-look="rivalry"] .pad{padding:0 20px}
html[data-look="rivalry"] .metarow{border-top:1px solid var(--line2);margin-top:13px}
html[data-look="rivalry"] .metacell{border-right:1px solid var(--line2);padding:10px 0 12px}
html[data-look="rivalry"] .metacell .v{font-family:var(--disp);font-size:24px;font-weight:800;letter-spacing:-.03em}
html[data-look="rivalry"] .metacell .l{font-family:var(--mono);font-weight:400;letter-spacing:.02em;font-size:8px}
html[data-look="rivalry"] .card{border-radius:0;background:var(--panel);border-color:var(--line2)}
html[data-look="rivalry"] .rowbtn{border-radius:0;background:var(--panel);border-color:var(--line2)}
html[data-look="rivalry"] .trow .nm{font-size:18px;font-weight:800;letter-spacing:-.03em}
html[data-look="rivalry"] .trow .pts{font-family:var(--disp);font-size:21px;font-weight:800}
html[data-look="rivalry"] .sect .ln{background:var(--line2)}
html[data-look="rivalry"] .av{border-radius:0}
html[data-look="rivalry"] .prog{border-radius:0;height:5px}
html[data-look="rivalry"] .prog i{border-radius:0;background:var(--skin)}
html[data-look="rivalry"] .tab span{font-family:var(--mono);font-size:8.5px;letter-spacing:.02em}
/* BEAT THEM AND THE FIELD DRAINS TO BLACK. Set by applyRival() once you are
   ahead of today's rival — the one state change in the app that is a reward
   rather than a notification. */
html[data-look="rivalry"][data-beat="1"]{--hero:linear-gradient(168deg,#141414 0%,#0D0D0D 58%,var(--bg) 100%)}
/* ===========================================================================
   THE FIELD, PROMOTED FROM A BAND TO THE APP — rivalry tuned toward HEAT.
   Josiah, 2026-09-14, picking HEAT out of three: "take heavy inspiration from
   what we had with rivalry ... it just needs to be refined and tuned".

   RIVALRY ALREADY PROMISED THIS IN WORDS AND DID NOT DO IT. editions/rivalry.js
   writes "It wears their colour until you pass them" while the colour stopped at
   the hero's bottom border, ~300px down a 1657px screen. HEAT's argument is that
   the PHONE wears the state, so band, channel bar, tabs and home indicator go
   with it. That is a token swap, not a rewrite: every shell surface in
   styles.css already reads var(--bar), and #app reads var(--bg)/var(--t1).

   THE TRIGGER IS `.rv-gap.dn`, NOT the absence of [data-beat]. Precision matters
   because absent-beat is FOUR states, not one: behind, level, no rival at all,
   and neither of you in a live challenge. duelBand() already separates them into
   .dn / .lvl / .solo / .none, so `.dn` means exactly "known, and you are behind"
   and a solo crew can never wake a red screen. Keying off :not([data-beat])
   would have painted the app red for somebody with nobody to race, which is the
   opposite of what the colour says.

   SCOPED BY :has() TO THE SCREEN THAT CARRIES THE DUEL. HEAT fields three of its
   five screens (FIELDED={today,race,drop}) and keeps crew and settle black —
   colour where your position is at stake, not everywhere. .rv-gap only renders
   inside the home hero, so :has() gets the same rule without app.js needing to
   publish the current screen, and app.js is not this lane's file. GAMES is the
   second candidate and is deliberately NOT in this pass.

   THE RED IS #FF4438 — THE ACCENT THE APP ALREADY HAS, AND IT WON ON NUMBERS.
   Contrast of #0B0B0B ink against each candidate ground:

     #FF4438  settled accent       5.75:1   <- this one
     #FF3B14  HEAT's own field     5.52:1
     #EC3013  broadcast deep red   4.69:1   fails AA for body

   So no new colour enters the app, and "red is liability" and "red is the ground
   when you are behind" become the same red rather than two that nearly match.

   INK IS BLACK ON IT, MEASURED, NOT ASSUMED: bone #EFEAE3 on this red is 2.86:1
   and white is 3.42:1 — both fail. The ramp below is 5.75 / 5.44 / 4.88, all
   clear of 4.5. That is also why the accent inverts: a #FF4438 rule on a #FF4438
   ground is invisible, so --gold becomes ink and --onGold becomes the field.
   =========================================================================== */
html[data-look="rivalry"]:has(.rv-gap.dn){
  --void:#FF4438; --bg:#FF4438; --bar:#FF4438;
  --t1:#0B0B0B; --t2:#2B0600; --t3:#3A1008;          /* 5.75 / 5.44 / 4.88 */
  --line:rgba(11,11,11,.32); --line2:rgba(11,11,11,.17);
  --panel:rgba(11,11,11,.07); --panel2:rgba(11,11,11,.12); --panel3:rgba(11,11,11,.18);
  --track:rgba(11,11,11,.18); --press:rgba(11,11,11,.11);
  /* The accent has to leave the hue it is standing on. */
  --gold:#0B0B0B; --gold2:#000000; --onGold:#FF4438; --goldWash:rgba(11,11,11,.10);
  --red:#0B0B0B; --redFill:#0B0B0B; --redDot:#0B0B0B; --redWash:rgba(11,11,11,.10);
  /* GREEN IS GONE HERE, DELIBERATELY. "Earned things are bone, red is liability"
     leaves no job for a third hue, and on this ground #7BE0A4 measures 2.2:1. */
  --green:#0B0B0B; --onGreen:#FF4438; --greenWash:rgba(11,11,11,.08);
  --blue:#0B0B0B;
  --skinInk:#0B0B0B;                                 /* a mid hue cannot read on this */
  --scrim:rgba(11,11,11,.72); --fade:rgba(255,68,56,0);
  --shadow:0 -1px 0 rgba(11,11,11,.32), 0 -20px 44px rgba(11,11,11,.30);
  --onRed:#FF4438;
  /* The hero stops being a band and becomes the same surface as everything else —
     the whole point of promoting it. */
  --hero:transparent;
}
/* The diagonal livery was a tint of the rival on black; on the field it would be
   a second red on red. It becomes a shadow of the ground instead, so the mark
   survives without inventing a hue. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-field{background:#0B0B0B;opacity:.07}
/* Its own bottom border is the last thing still drawing the hero as a card. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-hero{border-bottom-color:transparent}
/* The gap number led in --gold, which is now ink — correct, and it makes the
   number the loudest thing on the screen, which is what being behind should be. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-gap.dn .rv-num{color:var(--t1)}
/* THE AVATAR IS AN INLINE STYLE AND INLINE BEATS A TOKEN. av() in screens.js
   writes style="background:<member colour>" because the colour is a row anybody
   in the crew can write and it is allowlisted at the sink. Member colours are
   mid-saturation hues picked to be told apart on black; on this field the one in
   the demo crew is a #2C6FE8 blue, and it was the loudest wrong note on the
   screen. background-COLOR rather than the shorthand, so a member who has
   actually uploaded a photo keeps it.  screens.js is the ship lane's file, which
   is the other reason this is done here. */
html[data-look="rivalry"]:has(.rv-gap.dn) .av{
  background-color:#0B0B0B !important;color:#FF4438}
/* The livery was a rotated square of --skin at .20 on black, which reads as a
   corner mark. Re-tinted to ink it grew a hard visible edge instead, so it drops
   to where it is a change in the field rather than a shape on it. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-field{opacity:.045}
/* SPACING WAS DOING A BORDER'S JOB. The hero paid 24px of its own bottom padding
   and the next block paid 40px of margin, and that 64px was legible only because
   a rule sat between them. Take the rule away and it is a hole: measured on the
   fold, the run from "It wears their colour" to "ON THIS DEVICE" was the largest
   empty space on a screen that is otherwise too long. Removing the card has to
   change the rhythm too, or the composition is just the old one with the lines
   rubbed out. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-hero{padding-bottom:10px}
/* THE ONE FAILURE THIS CHANGE INTRODUCED, and the control is what identified it.
   contrast.js swept both states: COOL (unchanged) reports 7 failures and HOT
   reports 8, and 7 of the 8 are the same elements in both — .rv-h2h and the
   scoreline dashes are rivalry's pre-existing faults, not this palette's. The
   eighth is mine: span.conn ("THIS DEVICE") sits on --panel, so its effective
   ground is a lightened field rather than the field, and --t2 #2B0600 measured
   3.89:1 there against the 4.5 it needs. Ink, not muted, on that one pill.
   Running the sweep on the OLD state as well is the only reason this is
   attributable rather than a list of eight things to argue about. */
/* Ink alone was not enough - 3.89 went to 4.12, still under 4.5, because the pill
   carries its own lighter panel and the ink was already as dark as ink gets. So the
   PILL moves instead of the text: filled with ink, lettered in the field, which is
   5.75:1 by construction and matches what the avatar does two rules up. */
html[data-look="rivalry"]:has(.rv-gap.dn) .conn{
  background:#0B0B0B;color:#FF4438;border-color:#0B0B0B}
html[data-look="rivalry"]:has(.rv-gap.dn) .conn i,
html[data-look="rivalry"]:has(.rv-gap.dn) .conn .dot{background:#FF4438}

/* A margin-top rule on .rv-blk:first-of-type was here and did NOTHING: .rv-head is
   also a DIV, so :first-of-type matched the head and never a block. Measured in the
   running app — the four .rv-blk gaps stayed at 40/40/40/34px. Removed rather than
   left in, because a rule that has never applied reads as a decision that was made.
   The density it was reaching for is a composition job, not a spacing one: this
   screen is 1618px against HEAT's 1050, and that is the next pass. */




/* ===========================================================================
   SIGNATURES. One mechanism per direction, rendered by the sig* functions in
   screens.js and only ever present for the style that owns it — which is why
   these selectors do not need a [data-style] prefix.
   =========================================================================== */

/* ---- TOLERANCE: confidence intervals ----
   A bar with a whisker on it. The fill is the measured total; the whisker is
   the device tolerance around it. Two overlapping whiskers mean the app will
   not name a leader, which is the uncomfortable part of this direction. */
.sigci{display:block;position:relative;height:8px;margin-top:7px;background:var(--panel2)}
.sigci i{position:absolute;top:0;bottom:0;left:0;background:var(--t2);transform-origin:left}
.sigci u{position:absolute;top:-3px;bottom:-3px;border-left:1px solid var(--gold);
  border-right:1px solid var(--gold);background:rgba(232,163,61,.14)}
.sigtie{display:flex;gap:9px;align-items:flex-start;padding:13px 0;border-top:1px solid var(--line)}
.sigtie .mk{font-family:var(--mono);color:var(--gold);font-size:13px;flex:none;line-height:1.3}
.sigtie p{margin:0;font-size:13.5px;line-height:1.5;color:var(--t1)}
.sigtie p b{color:var(--gold);font-weight:600}
.sigprov{display:flex;gap:10px;flex-wrap:wrap;margin-top:6px}
.sigprov span{font-family:var(--mono);font-size:10px;letter-spacing:.04em;color:var(--t3)}

/* ---- POSITION: the book ----
   Implied probability per member, as a price ladder. Up and down are the only
   hues in this direction, so the sign of the move is the only colour here. */
.sigbook{margin-top:2px}
.sigbook .row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--line2)}
.sigbook .row:last-child{border-bottom:0}
.sigbook .nm{flex:1;min-width:0;font-size:14.5px;font-weight:500;letter-spacing:-.02em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sigbook .px{font-family:var(--mono);font-size:16px;font-weight:400;letter-spacing:-.02em;
  min-width:52px;text-align:right}
.sigbook .mv{font-family:var(--mono);font-size:10.5px;min-width:46px;text-align:right;color:var(--t3)}
.sigbook .mv.up{color:var(--green)}
.sigbook .mv.dn{color:var(--red)}
.sigbook .bar{position:relative;height:3px;background:var(--panel2);margin-top:-4px}
.sigbook .bar i{position:absolute;top:0;bottom:0;left:0;width:100%;background:var(--gold);
  transform-origin:left;transition:transform var(--d) var(--ease)}

/* ---- THE MONTH: the grid IS the app ----
   Six people by however many days the month has run. A missed day is a hole,
   and a run of holes is an elimination you can see from across the room. */
.siggrid{margin-top:4px;overflow-x:auto;overscroll-behavior-x:contain;padding-bottom:4px}
.siggrid table{border-collapse:collapse}
.siggrid th{font-family:var(--mono);font-size:8.5px;font-weight:400;color:var(--t3);
  padding:0 0 5px;text-align:center;min-width:13px}
.siggrid th.who{text-align:left;padding-right:9px;font-family:var(--disp);font-size:11px;
  font-weight:700;color:var(--t2);position:sticky;left:0;background:var(--bg)}
.siggrid td{padding:0 1px 2px 0}
.siggrid td.who{font-family:var(--disp);font-size:13px;font-weight:700;letter-spacing:-.02em;
  color:var(--t1);padding-right:9px;white-space:nowrap;position:sticky;left:0;background:var(--bg)}
.siggrid td.who.me{color:var(--gold)}
.siggrid b{display:block;width:13px;height:13px;background:var(--panel3);cursor:pointer}
.siggrid b.hit{background:var(--t1)}
.siggrid b.part{background:var(--t3)}
.siggrid b.hole{background:none;box-shadow:inset 0 0 0 1px var(--line2)}
.siggrid b.today{box-shadow:inset 0 0 0 1px var(--gold)}
.siggrid b.sel{box-shadow:inset 0 0 0 2px var(--gold)}
.sigcell{border-top:1px solid var(--line);margin-top:12px;padding:12px 0 0}
.sigcell .k{margin-bottom:5px}
.sigcell p{margin:0;font-size:14px;line-height:1.5;color:var(--t1)}
.sigkey{display:flex;gap:13px;flex-wrap:wrap;margin-top:10px}
.sigkey span{display:flex;align-items:center;gap:5px;font-family:var(--mono);font-size:9.5px;color:var(--t3)}
.sigkey i{width:10px;height:10px;display:block;background:var(--t1)}
.sigkey i.part{background:var(--t3)}
.sigkey i.hole{background:none;box-shadow:inset 0 0 0 1px var(--line)}

/* ---- OBLIGATION: the standing sentence ----
   Who owes whom, as a pull quote at 30px with the pay-rate as a byline. The
   true italic is the point: it is the only place in the app where a number is
   emphasised by the typeface rather than by a colour. */
.sigquote{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:22px 0;margin:4px 0 0}
.sigquote p{margin:0;font-family:var(--disp);font-size:30px;line-height:1.2;
  font-weight:400;letter-spacing:-.018em;color:var(--t1)}
.sigquote p em{font-style:italic;color:var(--gold)}
.sigquote .by{display:block;margin-top:14px;font-family:var(--mono);font-size:10px;
  letter-spacing:.11em;text-transform:uppercase;color:var(--t3)}
.sigweb{margin-top:16px}
.sigweb .ln{display:flex;align-items:baseline;gap:8px;padding:9px 0;border-bottom:1px solid var(--line2)}
.sigweb .ln:last-child{border-bottom:0}
.sigweb .ln span{font-family:var(--disp);font-size:15.5px;line-height:1.45;color:var(--t2)}
.sigweb .ln b{font-weight:600;color:var(--t1)}
.sigweb .ln em{font-style:italic;color:var(--gold);font-weight:400}

/* ---- RESTRAINT: the refusal ----
   One number, one verb, and the standings withheld until you have logged. The
   hairline IS the relief effect — there is exactly one in the whole screen. */
.sigone{padding:70px 0 0;text-align:left}
.sigone .fig{font-family:var(--disp);font-size:104px;line-height:.88;font-weight:400;
  letter-spacing:-.045em;color:var(--t1)}
.sigone .unit{display:block;margin-top:18px;font-family:var(--mono);font-size:11px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--t3)}
.sigone .hair{height:1px;background:var(--line);margin:54px 0 0}
.sigone .say{margin:26px 0 0;font-family:var(--mono);font-size:14.5px;line-height:1.6;color:var(--t2);max-width:26em}
.sigheld{padding:60px 0 0}
.sigheld .fig{font-family:var(--disp);font-size:54px;line-height:1.04;font-weight:400;
  letter-spacing:-.03em;color:var(--t1);max-width:16em}
.sigheld .hair{height:1px;background:var(--line);margin:44px 0 0}
.sigheld .say{margin:24px 0 0;font-family:var(--mono);font-size:14px;line-height:1.6;color:var(--t3);max-width:26em}

/* ---- RIVALRY: today's grudge ----
   One person, their colour, and nothing else above the fold. */
.sigrival{padding:4px 0 0}
.sigrival .top{display:flex;align-items:center;gap:13px}
.sigrival .vs{font-family:var(--mono);font-size:9px;letter-spacing:.04em;color:var(--t3)}
.sigrival .who{font-family:var(--disp);font-size:40px;font-weight:800;line-height:.98;
  letter-spacing:-.04em;color:var(--t1);margin-top:3px}
.sigrival .gap{display:flex;align-items:baseline;gap:9px;margin-top:16px;
  border-top:1px solid var(--line2);padding-top:13px}
.sigrival .gap .n{font-family:var(--disp);font-size:34px;font-weight:800;letter-spacing:-.04em}
.sigrival .gap .n.up{color:var(--green)}
.sigrival .gap .n.dn{color:var(--skin)}
.sigrival .gap .w{font-family:var(--mono);font-size:10px;letter-spacing:.02em;color:var(--t3);line-height:1.4}
.sigrival .field{height:4px;background:var(--skin);margin:15px 0 0}

/* ---- TERMINAL: the log ----
   Replaces the story bar with a line of output. Same state, same stories, read
   as a system writing them down rather than a graphic announcing them. */
.siglog{margin:13px -14px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--panel);padding:9px 14px}
.siglog .ln{display:flex;gap:9px;align-items:baseline;font-family:var(--mono);font-size:11.5px;line-height:1.55}
.siglog .ln+.ln{margin-top:3px}
.siglog .ts{color:var(--t3);flex:none}
.siglog .lv{flex:none;font-weight:600}
.siglog .lv.i{color:var(--green)}
.siglog .lv.w{color:var(--gold)}
.siglog .lv.n{color:var(--blue)}
.siglog .tx{color:var(--t2);min-width:0}
.siglog .tx b{color:var(--t1);font-weight:600}
.siglog .cur{display:inline-block;width:6px;height:13px;background:var(--gold);
  vertical-align:-2px;animation:blip 1.1s steps(1) infinite}

/* ---- LEDGER: the position column ----
   Up, down, owed, due — the four numbers this direction thinks the app is for,
   above anything about running. */
.sigpos{border-top:1px solid var(--line);border-bottom:1px solid var(--line);margin:2px 0 0}
.sigpos .ln{display:flex;align-items:baseline;gap:10px;padding:11px 0;border-bottom:1px solid var(--line2)}
.sigpos .ln:last-child{border-bottom:0}
.sigpos .l{flex:1;font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--t3)}
.sigpos .v{font-family:var(--mono);font-size:19px;font-weight:500;letter-spacing:-.01em;color:var(--t1)}
.sigpos .v.up{color:var(--green)}
.sigpos .v.dn{color:var(--red)}
.sigpos .n{font-family:var(--mono);font-size:10px;color:var(--t3);min-width:58px;text-align:right}

/* ---- RECEIPT: the slip ----
   A torn edge and printed totals. The zig-zag is a conic gradient rather than
   an image so it follows the ground colour.  */
.sigslip{background:var(--panel);border:1px dashed var(--line);border-bottom:0;
  margin:2px 0 0;padding:15px 15px 17px}
.sigslip .hd{display:flex;justify-content:space-between;align-items:baseline;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--t3)}
.sigslip .ttl{font-family:var(--mono);font-size:16px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--t1);margin-top:11px}
.sigslip .ln{display:flex;align-items:baseline;gap:7px;font-family:var(--mono);font-size:12.5px;
  color:var(--t2);margin-top:9px}
.sigslip .ln .dots{flex:1;border-bottom:1px dotted var(--line);transform:translateY(-3px)}
.sigslip .ln .v{color:var(--t1);font-weight:600}
.sigslip .tot{display:flex;align-items:baseline;gap:7px;margin-top:13px;padding-top:11px;
  border-top:1px dashed var(--line);font-family:var(--mono);font-size:15px;font-weight:600;color:var(--t1)}
.sigslip .tot .dots{flex:1}
.sigslip .stamp{display:inline-block;margin-top:14px;padding:4px 9px;font-family:var(--mono);
  font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--red);border:2px solid var(--red);transform:rotate(-3.5deg)}
.sigtear{height:9px;background:
  conic-gradient(from 135deg at 50% 0, var(--panel) 0 25%, transparent 0 100%) 0 0/12px 9px repeat-x;
  filter:drop-shadow(0 1px 0 var(--line))}

/* ---- BROADCAST keeps the story bar, which is already in styles.css ---- */

/* ---- the picker itself ----
   A palette swatch would have been the dishonest way to show these, so each
   row carries the style's own thesis and names the prototype it came from. */
.stylerow{display:block;width:100%;text-align:left;background:var(--panel);border:1px solid var(--line2);
  border-radius:var(--rad);padding:13px 14px;margin-top:8px;color:var(--t1);cursor:pointer;
  font-family:var(--disp)}
.stylerow:active{background:var(--panel2)}
.stylerow[aria-pressed="true"]{border-color:var(--gold);background:var(--panel2)}
.stylerow .hd{display:flex;align-items:center;gap:8px}
.stylerow .nm{font-size:16px;font-weight:700;letter-spacing:-.015em;flex:1;min-width:0}
.stylerow .th{display:block;margin-top:5px;font-size:13px;line-height:1.45;color:var(--t2)}
.stylerow .sg{display:block;margin-top:7px;font-size:12px;line-height:1.4;color:var(--t3)}
.stylerow .dna{display:flex;gap:7px;flex-wrap:wrap;margin-top:9px}
.stylerow .dna span{font-family:var(--mono);font-size:9.5px;letter-spacing:.04em;color:var(--t3);
  border:1px solid var(--line2);border-radius:var(--radt);padding:2px 6px}

/* THE FOLD. Josiah, 2026-09-14: "just put them under like a drop down so I can
   hide them when I want but have the other 3 visible". The summary is styled as
   a row of the same family but deliberately quieter than a .stylerow — no panel
   fill, no border — because it is a door, not a fourteenth choice.

   44px MINIMUM, NOT 44px NOMINAL. padding+line-height here measures 45px; the
   tap-target sweep in the shoot script is what this has to survive, and the one
   element already failing it (the demo banner's EXIT DEMO, 26px) is not mine. */
.morestyles{margin-top:8px}
.morestyles>summary{display:flex;align-items:center;gap:8px;list-style:none;cursor:pointer;
  padding:13px 4px;font-family:var(--disp);font-size:13px;font-weight:700;
  letter-spacing:.02em;color:var(--t3);border-top:1px solid var(--line2)}
.morestyles>summary::-webkit-details-marker{display:none}
/* The triangle is drawn, not borrowed: the platform marker sits on the far left
   and inherits a size we do not control, and this one has to turn. */
.morestyles>summary::after{content:'';width:7px;height:7px;margin-left:auto;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .18s ease}
.morestyles[open]>summary::after{transform:rotate(-135deg) translate(-2px,-2px)}
.morestyles[open]>summary{color:var(--t2)}
.morestyles>summary .ct{font-family:var(--mono);font-size:10px;font-weight:400;
  border:1px solid var(--line2);border-radius:var(--radt);padding:2px 6px;color:var(--t3)}
/* The first folded row would otherwise touch the summary's rule. */
.morestyles[open]>.stylerow:first-of-type{margin-top:10px}
@media (prefers-reduced-motion:reduce){.morestyles>summary::after{transition:none}}

/* ===========================================================================
   RIVALRY, THE EDITION — composition, not palette.
   Appended 2026-09-11. Everything above this line skins the BASE app in
   rivalry's colours; everything below styles the screens that only exist in
   editions/rivalry.js and have no counterpart in the base app.

   Scoped under .rv so none of it can reach a screen this edition does not own.
   Uses the tokens declared in the rivalry block above — --skin is written to
   the root per-rival by applyRival(), so the accent here is a person.
   =========================================================================== */
html[data-look="rivalry"] .rv-wrap{padding:0 20px 40px}

/* ---- crew header ---- */
html[data-look="rivalry"] .rv-head{padding:18px 0 0}
html[data-look="rivalry"] .rv-crewname{
  font-family:var(--mono);font-size:9px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--t3)}
html[data-look="rivalry"] .rv-count{
  font-family:var(--disp);font-weight:800;font-stretch:100%;letter-spacing:-.04em;
  font-size:40px;line-height:.96;margin:10px 0 0;color:var(--t1)}
html[data-look="rivalry"] .rv-note{
  margin:12px 0 0;max-width:34ch;font-size:13px;line-height:1.5;color:var(--t2)}

/* ---- THE HERO. The rival, edge to edge, at the top of the app. -------------
   Replaces the old .rv-duel card. Josiah on the card version: "It doesn't look
   great... It should feel like a punchy app... It needs to have character and
   not just feel like it's been vibe coded in ten minutes."
   He was right, and the diagnosis was ORDER before it was decoration: the
   biggest thing on the screen was "six of you" at 40px, with the rival in a
   modest bordered box beneath it. That put the ROSTER first in the one
   direction whose entire thesis is that today is about a single person.
   The hero now runs into the corners, because a rival's colour that stops 20px
   short of the edge is a card, and a card is a thing the app CONTAINS. This is
   the app WEARING them, which is what styles.js promised.  -------------------*/
html[data-look="rivalry"] .rv-hero{
  display:block;position:relative;overflow:hidden;cursor:pointer;
  padding:26px 20px 24px;border-bottom:1px solid var(--line);
  background:var(--hero);color:var(--t1);
  transition:background var(--d-slow) var(--ease)}
/* THE FIELD DRAINS TO BLACK WHEN YOU LEAD. The mechanism styles.js describes
   in words — "the field is black while you stay there" — is this rule. */
html[data-look="rivalry"] .rv-hero.up{
  background:linear-gradient(168deg,rgba(255,255,255,.055) 0%,var(--bg) 58%)}
html[data-look="rivalry"] .rv-hero:active{background:var(--press)}
html[data-look="rivalry"] .rv-hero:focus-visible{
  outline:2px solid var(--gold);outline-offset:-4px}
/* A single diagonal of the rival's colour behind the type. One mark, no
   gradient soup: it reads as a livery rather than as a glow. */
html[data-look="rivalry"] .rv-field{
  position:absolute;right:-60px;top:-40px;width:190px;height:190px;
  background:var(--skin);opacity:.20;transform:rotate(28deg);
  pointer-events:none}
html[data-look="rivalry"] .rv-hero.up .rv-field{opacity:.05}

html[data-look="rivalry"] .rv-kick{
  display:block;font-family:var(--mono);font-size:8px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--t2);position:relative}
/* THE WIDTH AXIS IS THE WHOLE REASON THIS FACE WAS CHOSEN. Bricolage carries
   wdth 75-100; the name rides wide and the labels ride narrow, which is a
   register change no recolour can imitate. */
html[data-look="rivalry"] .rv-vs{
  font-family:var(--disp);font-weight:800;font-stretch:100%;
  font-size:clamp(38px,13vw,54px);line-height:.9;letter-spacing:-.05em;
  text-transform:uppercase;margin:8px 0 0;color:var(--t1);
  position:relative;word-break:break-word}
html[data-look="rivalry"] .rv-hero.solo .rv-vs{color:var(--t2)}
html[data-look="rivalry"] .rv-sub{
  margin:12px 0 18px;max-width:32ch;font-size:13px;line-height:1.5;color:var(--t2);
  position:relative}

/* The scoreline: second-biggest thing on the screen, because "3-1 against you"
   is the sentence this direction exists to say. It was 9.5px of mono. */
html[data-look="rivalry"] .rv-score{
  display:flex;align-items:baseline;gap:9px;margin-top:16px;position:relative}
html[data-look="rivalry"] .rv-sc{
  font-family:var(--disp);font-weight:800;font-stretch:88%;font-size:30px;
  line-height:1;letter-spacing:-.03em;color:var(--gold);
  font-variant-numeric:tabular-nums}
html[data-look="rivalry"] .rv-sc i{font-style:normal;opacity:.42;margin:0 2px}
html[data-look="rivalry"] .rv-sc.new{font-size:19px;letter-spacing:.04em}
html[data-look="rivalry"] .rv-sc-l{
  font-family:var(--mono);font-size:9px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--t2)}

html[data-look="rivalry"] .rv-gap{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:0 8px;position:relative;
  margin-top:18px;padding-top:15px;border-top:1px solid var(--line2)}
html[data-look="rivalry"] .rv-gap.none{
  font-size:12.5px;color:var(--t2);display:block}
html[data-look="rivalry"] .rv-num{
  font-family:var(--disp);font-weight:800;font-stretch:100%;font-size:40px;
  line-height:.95;letter-spacing:-.045em;font-variant-numeric:tabular-nums}
html[data-look="rivalry"] .rv-gap.up .rv-num{color:var(--green)}
html[data-look="rivalry"] .rv-gap.dn .rv-num{color:var(--gold)}
html[data-look="rivalry"] .rv-gap.lvl .rv-num{color:var(--t1);font-size:30px}
html[data-look="rivalry"] .rv-unit{
  font-family:var(--mono);font-size:11px;color:var(--t2);text-transform:uppercase}
html[data-look="rivalry"] .rv-say{
  flex:1 0 100%;margin-top:7px;font-size:12px;line-height:1.45;color:var(--t2);
  max-width:34ch}

/* ---- THE FOLD, AT HEAT'S SCALE -------------------------------------------
   Not state-scoped, deliberately: colour is what changes when you pass somebody,
   and an app that also re-typesets itself at that moment is two events instead
   of one. The composition belongs to the direction, the temperature to the state.

   duelBand() now emits gap-then-record (see the note in editions/rivalry.js), so
   the live number is second in the hero instead of fourth, and this is the type
   scale that goes with that order. HEAT leads its fold with one figure at ~108px;
   rivalry was leading with a 50px name over a 30px month record and putting the
   number you can still do something about at 40px, fourth.

   clamp() rather than a fixed size because this figure is real data, not the
   artboard's 2.4: it runs from "−0.4" to five characters plus a sign, and at
   24vw the widest case still clears the 350px of usable width at 390. */
html[data-look="rivalry"] .rv-num{
  font-size:clamp(58px,24vw,96px);line-height:.86;letter-spacing:-.055em}
html[data-look="rivalry"] .rv-gap{margin-top:14px;padding-top:14px}
html[data-look="rivalry"] .rv-unit{font-size:14px;letter-spacing:.06em}
html[data-look="rivalry"] .rv-say{font-size:13px;margin-top:10px;max-width:30ch}
/* LEVEL is a word, not a figure, and a word set at 96px wraps and looks like a
   mistake. It keeps its own size and gains only what the new rhythm gives it. */
html[data-look="rivalry"] .rv-gap.lvl .rv-num{font-size:44px;letter-spacing:-.035em}
/* The month record is now the SECOND fact, so it stops competing with the first.
   It was 30px sitting above the 40px gap - near-parity, which is what made the
   fold read as two headlines rather than a statement and its footnote. */
html[data-look="rivalry"] .rv-score{margin-top:18px}
html[data-look="rivalry"] .rv-sc{font-size:22px}
html[data-look="rivalry"] .rv-sc.new{font-size:16px}
/* GREEN GOES, AND MY OWN CHANGE IS WHAT MADE IT UNTENABLE. .rv-gap.up .rv-num
   was --green #7BE0A4 and survived review at 40px as a small positive marker. At
   clamp(58,24vw,96) it is the largest object on the black screen, and the rule
   this redesign settled is that RED MEANS LIABILITY AND ANYTHING EARNED IS BONE —
   a third hue carrying "you are winning" has no place in that scheme, and it was
   the loudest thing in the app contradicting it. Bone also makes the two
   temperatures read as one product: ink on the field when you are behind, bone on
   black when you are ahead, the same figure in both.
   Amplifying something is a decision about it; the size change is what put this
   on the table, so it gets resolved here rather than logged as pre-existing. */
html[data-look="rivalry"] .rv-gap.up .rv-num{color:var(--t1)}
/* ===========================================================================
   HEAT AND HEAT BLACK ARE THE SAME APP WITH THE FIELD ON OR OFF.
   Josiah, 2026-09-14, on what the picker should hold: "broadcast, volt, heat,
   board, both the red and black versions of heat".

   Every rivalry rule above now keys on data-look rather than data-style, which
   is the move this stylesheet already made for ledger so claudedesign could wear
   it — see the note at the top of the ledger block. applyStyle() sets
   data-look = s.look || s.key, so `heat` and `heatblack` both declare
   look:'rivalry' and inherit all 158 rules without one of them being duplicated.

   THE ONLY DIFFERENCE IS THIS BLOCK. heatblack refuses the field: same
   composition, same type scale, same 96px figure, but it never comes up red. So
   the choice in the picker is a real one — one app tells you where you stand with
   the entire screen, the other keeps its voice down and lets the number do it.
   Written as a revert of the tokens rather than as a competing :has() rule,
   because two rules racing on specificity is how one of them quietly wins in a
   state nobody tested.
   =========================================================================== */
html[data-style="heatblack"]:has(.rv-gap.dn){
  --void:#050505; --bg:#0B0B0B; --bar:#0B0B0B;
  --t1:#FFFFFF; --t2:#A8A8A8; --t3:#8E8E8E;
  --line:rgba(255,255,255,.16); --line2:rgba(255,255,255,.09);
  --panel:rgba(255,255,255,.045); --panel2:rgba(255,255,255,.08);
  --panel3:rgba(255,255,255,.13);
  --track:rgba(255,255,255,.10); --press:rgba(255,255,255,.08);
  --gold:#FF4438; --gold2:#E8382B; --onGold:#0B0B0B; --goldWash:rgba(255,68,56,.12);
  --red:#FF7060; --redFill:#8E2A18; --redDot:var(--gold); --redWash:rgba(255,68,56,.08);
  --green:#7BE0A4; --onGreen:#071409; --greenWash:rgba(255,255,255,.05);
  --blue:#8FB6FF; --skinInk:color-mix(in oklab, var(--skin) 62%, #FFFFFF);
  --scrim:rgba(5,5,5,.8); --fade:rgba(11,11,11,0); --onRed:#fff;
  --shadow:0 -1px 0 var(--line), 0 -20px 44px rgba(0,0,0,.8);
  --hero:linear-gradient(168deg,color-mix(in oklab,var(--skin) 26%,#0B0B0B) 0%,
                                color-mix(in oklab,var(--skin) 9%,#0B0B0B) 58%,var(--bg) 100%);
}
/* and the three consequences of the field, put back */
html[data-style="heatblack"]:has(.rv-gap.dn) .av{
  background-color:revert !important;color:inherit}
html[data-style="heatblack"]:has(.rv-gap.dn) .conn{
  background:revert;color:revert;border-color:revert}
html[data-style="heatblack"]:has(.rv-gap.dn) .rv-field{display:block;opacity:.20}
html[data-style="heatblack"]:has(.rv-gap.dn) .rv-hero{
  border-bottom-color:var(--line);padding-bottom:24px}
html[data-style="heatblack"]:has(.rv-gap.dn) .rv-gap.dn .rv-num{color:var(--gold)}



/* The sign, sized as punctuation rather than as a digit. .52em keeps it legible
   at every clamp step without it weighing the same as the figure, and the nudge
   keeps it optically centred on the numerals rather than sitting on the baseline
   of a much taller glyph. */
html[data-look="rivalry"] .rv-sgn{
  font-style:normal;font-size:.52em;vertical-align:.22em;margin-right:.02em}
/* THE LIVERY COMES OFF THE FIELD ENTIRELY. On black it is the mark that says
   whose day this is. On the field the screen IS that statement, so a wedge of
   the same hue behind the figure is a second voice saying the same thing — and
   at the new type size it crosses the number. It stays in the cool state, where
   it still has a job. */
html[data-look="rivalry"]:has(.rv-gap.dn) .rv-field{display:none}


/* ---- blocks and section heads ---- */
html[data-look="rivalry"] .rv-blk{margin-top:40px}
html[data-look="rivalry"] .rv-last{margin-top:34px;padding-bottom:8px}
html[data-look="rivalry"] .rv-sec{
  display:flex;align-items:baseline;gap:10px;padding-bottom:10px;
  border-bottom:1px solid var(--line2);
  font-family:var(--mono);font-size:9px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--t2)}
html[data-look="rivalry"] .rv-r{margin-left:auto;color:var(--t3)}

/* ---- a person, read as a grudge ----
   No rank column. Deliberately: this is the one screen in the app where nobody
   is ranked, which is the thesis made structural. */
html[data-look="rivalry"] .rv-row{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:13px 0;border:0;border-bottom:1px solid var(--line2);
  background:none;color:var(--t1);cursor:pointer}
html[data-look="rivalry"] .rv-row:active{background:var(--press)}
html[data-look="rivalry"] .rv-row.me{border-bottom-color:var(--line)}
html[data-look="rivalry"] .rv-row-n{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
html[data-look="rivalry"] .rv-row-name{
  font-family:var(--disp);font-weight:800;font-size:17px;letter-spacing:-.03em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html[data-look="rivalry"] .rv-row.me .rv-row-name{color:var(--gold)}
html[data-look="rivalry"] .rv-row-s{font-family:var(--mono);font-size:9.5px;color:var(--t2)}
html[data-look="rivalry"] .rv-row-debt{font-family:var(--mono);font-size:9px;color:var(--red)}
html[data-look="rivalry"] .rv-row-v{
  font-family:var(--disp);font-weight:800;font-size:17px;letter-spacing:-.02em;
  margin-left:auto;white-space:nowrap}

/* ---- a running game ---- */
html[data-look="rivalry"] .rv-fx{
  display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  padding:14px 0;border:0;border-bottom:1px solid var(--line2);
  background:none;color:var(--t1);cursor:pointer}
html[data-look="rivalry"] .rv-fx:active{background:var(--press)}
html[data-look="rivalry"] .rv-fx-n{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}
html[data-look="rivalry"] .rv-fx-name{
  font-family:var(--disp);font-weight:800;font-size:16px;letter-spacing:-.03em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html[data-look="rivalry"] .rv-fx-s{font-family:var(--mono);font-size:9px;color:var(--t2)}

/* ---- a real empty state, because a crew with nothing running is the first
        thing anybody sees and the base app's matchday has nothing to say ---- */
html[data-look="rivalry"] .rv-empty{padding:22px 0 4px}
html[data-look="rivalry"] .rv-empty-h{
  font-family:var(--disp);font-weight:800;font-size:19px;letter-spacing:-.03em;color:var(--t1)}
html[data-look="rivalry"] .rv-empty p{
  margin:10px 0 0;max-width:32ch;font-size:12.5px;line-height:1.55;color:var(--t2)}

/* ---- buttons ---- */
html[data-look="rivalry"] .rv-act{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  min-height:48px;margin-top:16px;padding:0 18px;border:1px solid var(--line);
  font-family:var(--disp);font-weight:800;font-size:14px;letter-spacing:-.01em;
  background:none;color:var(--t1);cursor:pointer;
  transition:background var(--d-fast) var(--ease)}
html[data-look="rivalry"] .rv-act:active{background:var(--press)}
html[data-look="rivalry"] .rv-act.skin{
  background:var(--gold);border-color:var(--gold);color:var(--onGold)}
html[data-look="rivalry"] .rv-act.skin:active{filter:brightness(.92)}

/* ---- the story bar, replaced by one opponent ----
   The base app rotates seven stories here. A carousel says "here are seven
   things" on a screen that means "here is one". */
html[data-look="rivalry"] .rv-bug{
  display:flex;align-items:center;gap:10px;padding:0 20px;height:100%}
html[data-look="rivalry"] .rv-bug-lab{
  font-family:var(--mono);font-size:8px;letter-spacing:.1em;color:var(--t3)}
html[data-look="rivalry"] .rv-bug-who{
  font-family:var(--disp);font-weight:800;font-size:14px;letter-spacing:-.03em;
  color:var(--gold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html[data-look="rivalry"] .rv-bug-rec{
  margin-left:auto;font-family:var(--mono);font-size:9px;color:var(--t2)}

/* ---- THE MONTH, in the slot the standings table used to hold ----
   Days across, people down, a hole where somebody missed one. A different
   QUESTION from the table, not a different skin on it. */
html[data-look="rivalry"] .rv-month{margin-top:4px}
html[data-look="rivalry"] .rv-mrow{
  display:flex;align-items:center;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--line2)}
html[data-look="rivalry"] .rv-mname{
  font-family:var(--disp);font-weight:800;font-size:13px;letter-spacing:-.02em;
  width:72px;flex:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:var(--t2)}
html[data-look="rivalry"] .rv-mrow.me .rv-mname{color:var(--t1)}
/* The day's rival is named on this screen too, so the two tabs agree about who
   today is about rather than each picking their own subject. */
html[data-look="rivalry"] .rv-mrow.rival .rv-mname{color:var(--skinInk)}
html[data-look="rivalry"] .rv-mcells{display:flex;gap:3px;flex:1;min-width:0}
html[data-look="rivalry"] .rv-c{
  flex:1;min-width:0;height:20px;border-radius:0;display:block;
  background:var(--track)}
html[data-look="rivalry"] .rv-c.hit{background:var(--gold)}
html[data-look="rivalry"] .rv-c.part{background:color-mix(in oklab,var(--skin) 42%,var(--bg))}
/* A MISSED DAY IS A HOLE, not a faint cell. It is drawn as an absence — the
   one thing the month is for. */
html[data-look="rivalry"] .rv-c.hole{
  background:none;box-shadow:inset 0 0 0 1px var(--line2)}
html[data-look="rivalry"] .rv-c.today{box-shadow:inset 0 0 0 1.5px var(--t1)}
html[data-look="rivalry"] .rv-key{
  display:flex;gap:16px;margin-top:14px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.05em;color:var(--t3)}
html[data-look="rivalry"] .rv-key span{display:flex;align-items:center;gap:6px}
html[data-look="rivalry"] .rv-key .rv-c{width:14px;height:10px;flex:none}

@media (prefers-reduced-motion:reduce){
  html[data-look="rivalry"] .rv-act{transition:none}
}

/* ===========================================================================
   THE MONTH, THE EDITION — thirty days of everybody, and a cursor through them.
   Appended 2026-09-11. Everything above skins the BASE app in month's palette;
   this styles the screens that only exist in editions/month.js.

   Light direction: --bg #F2F0EB, vermilion #C0341B as a MARK and never a fill.
   Scoped under .mo so none of it reaches a screen this edition does not own.
   =========================================================================== */
.mo-wrap{padding:0 20px 40px}

/* ---- the date, which is the subject of this direction ---- */
.mo-head{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;padding:20px 0 0}
.mo-dow{
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--t2);
  text-transform:uppercase}
.mo-when{
  font-family:var(--mono);font-size:8.5px;letter-spacing:.12em;color:var(--onGold);
  background:var(--gold);padding:3px 6px}
.mo-big{
  flex:1 0 100%;font-family:var(--disp);font-weight:700;font-size:56px;
  line-height:.92;letter-spacing:-.045em;color:var(--t1);margin-top:4px;
  font-variant-numeric:tabular-nums}
.mo-note{
  margin:14px 0 0;max-width:36ch;font-size:13px;line-height:1.55;color:var(--t2)}

.mo-blk{margin-top:46px}
.mo-last{margin-top:46px;padding-bottom:8px}
.mo-sec{
  font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--t2);padding-bottom:8px;border-bottom:1px solid var(--t1)}

/* ---- THE GRID. The whole crew's month at once, which is the composition the
        base app cannot express. One column per day, sized off --days so a 14-day
        challenge and a 31-day one both fill the width. ---- */
.mo-grid{
  display:grid;grid-template-columns:26px repeat(var(--days),1fr);
  gap:2px;align-items:center}
.mo-t{
  font-family:var(--mono);font-size:7px;color:var(--t3);text-align:center;
  line-height:1;padding-bottom:4px;font-variant-numeric:tabular-nums}
.mo-r{display:contents}
.mo-who{
  font-family:var(--mono);font-size:8px;letter-spacing:.04em;color:var(--t2);
  text-transform:uppercase;padding-right:4px;white-space:nowrap;overflow:hidden}
.mo-r.me .mo-who{color:var(--gold);font-weight:500}
.mo-c{
  height:16px;background:var(--track);display:block}
/* The mark, never a fill: a logged day is vermilion, and it is the only colour
   on the screen. */
.mo-c.hit{background:var(--gold)}
.mo-c.part{background:var(--goldWash);
  box-shadow:inset 0 0 0 1px var(--gold)}
/* A MISSED DAY IS A HOLE — drawn as an absence with a rule under it, not as a
   faint fill. The whole thesis is that you can see the gaps. */
.mo-c.hole{
  background:none;box-shadow:inset 0 -1px 0 var(--line2)}
.mo-c.now{
  box-shadow:inset 0 0 0 1.5px var(--t1)}
.mo-c.hole.now{
  box-shadow:inset 0 0 0 1.5px var(--t1)}

/* ---- THE SCRUBBER — the signature. No other direction has one. ---- */
.mo-scrub{margin-top:18px}
.mo-scrub input[type=range]{
  -webkit-appearance:none;appearance:none;width:100%;height:22px;
  background:none;display:block;cursor:ew-resize}
.mo-scrub input[type=range]::-webkit-slider-runnable-track{
  height:2px;background:var(--line)}
.mo-scrub input[type=range]::-moz-range-track{
  height:2px;background:var(--line)}
/* 22px of thumb on a 2px track: the tap target has to clear 44px with the
   input's own height, and a hairline track with a real handle is the Swiss
   reading of a slider. */
.mo-scrub input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:12px;height:22px;margin-top:-10px;
  background:var(--t1);border:0;border-radius:0}
.mo-scrub input[type=range]::-moz-range-thumb{
  width:12px;height:22px;background:var(--t1);border:0;border-radius:0}
.mo-scrub input[type=range]:focus-visible{
  outline:2px solid var(--gold);outline-offset:3px}
.mo-cap{
  display:flex;justify-content:space-between;gap:8px;margin-top:6px;
  font-family:var(--mono);font-size:8px;letter-spacing:.08em;color:var(--t3)}
.mo-drag{color:var(--gold)}

.mo-key{
  display:flex;gap:14px;margin-top:16px;flex-wrap:wrap}
.mo-key i{
  display:flex;align-items:center;gap:5px;font-style:normal;
  font-family:var(--mono);font-size:8px;letter-spacing:.06em;color:var(--t3)}
.mo-key b{width:12px;height:10px;display:block;
  background:var(--track)}
.mo-key b.hit{background:var(--gold)}
.mo-key b.part{background:var(--goldWash);
  box-shadow:inset 0 0 0 1px var(--gold)}
.mo-key b.hole{background:none;
  box-shadow:inset 0 -1px 0 var(--line)}

/* ---- the three bands, rewritten in place on every scrub ---- */
.mo-band{
  display:flex;align-items:baseline;gap:12px;padding:12px 0;
  border-bottom:1px solid var(--line2)}
.mo-band:first-child{border-top:1px solid var(--t1)}
.mo-k{
  font-family:var(--mono);font-size:8.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--t3);width:64px;flex:none}
.mo-v{
  font-family:var(--disp);font-weight:500;font-size:15px;letter-spacing:-.02em;
  color:var(--t1);min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.mo-n{
  margin-left:auto;font-family:var(--mono);font-size:12px;color:var(--t2);
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---- crew ---- */
.mo-row{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:13px 0;border:0;border-bottom:1px solid var(--line2);
  background:none;color:var(--t1);cursor:pointer}
.mo-row:active{background:var(--press)}
.mo-nm{
  display:flex;flex-direction:column;gap:3px;min-width:0;flex:1;
  font-family:var(--disp);font-weight:500;font-size:15px;letter-spacing:-.02em}
.mo-sub{
  font-family:var(--mono);font-size:9px;color:var(--t2);font-weight:400;
  letter-spacing:0}
.mo-fig{
  font-family:var(--mono);font-size:13px;color:var(--t1);margin-left:auto;
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---- buttons ---- */
.mo-act{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  min-height:48px;padding:0 18px;border:1px solid var(--t1);
  font-family:var(--disp);font-weight:600;font-size:14px;letter-spacing:-.01em;
  background:var(--t1);color:var(--bg);cursor:pointer;
  transition:opacity var(--d-fast) var(--ease)}
.mo-act:active{opacity:.82}

/* ---- the bug slot: this direction's subject is a date ---- */
.mo-bug{
  display:flex;align-items:center;gap:10px;padding:0 20px;height:100%}
.mo-bug-d{
  font-family:var(--mono);font-size:10px;color:var(--gold);
  font-variant-numeric:tabular-nums}
.mo-bug-t{
  font-family:var(--disp);font-weight:500;font-size:13px;color:var(--t1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

@media (prefers-reduced-motion:reduce){
  .mo-act{transition:none}
}

/* ---- RIVALRY, second pass: the roster reads as a column of grudges ---------
   Added 2026-09-11 after Josiah: "keep going more in-depth on the rivalry
   section... It should feel like a punchy app... It needs to have character."
   The record moved out of the 9.5px subtitle into its own column, so it reads
   DOWN the list at a glance. That is what turns a roster into standings-free
   grudges instead of a contact list with numbers on it.
   -------------------------------------------------------------------------- */
html[data-look="rivalry"] .rv-head{padding:22px 0 0}
html[data-look="rivalry"] .rv-crewname{
  font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--t3)}
html[data-look="rivalry"] .rv-note{
  margin:10px 0 0;max-width:36ch;font-size:13.5px;line-height:1.5;color:var(--t2)}

/* Four columns: avatar, who, the head-to-head, the money. */
html[data-look="rivalry"] .rv-row{gap:11px}
html[data-look="rivalry"] .rv-row-name{font-size:16px}
html[data-look="rivalry"] .rv-row-s{
  font-family:var(--mono);font-size:9px;color:var(--t3);letter-spacing:.01em}
html[data-look="rivalry"] .rv-row-debt{
  color:var(--gold);font-weight:400}

/* NOTE ON PLACEMENT: this block lives HERE, not up with the other tuning.
   .rv-p and .rv-row get their padding in the second-pass roster section below
   the first one, so an identical-specificity override written earlier in the
   file loses on source order and changes nothing. It was written earlier, it
   measured as a no-op (1512px before, 1512px after), and that is how it was
   found — a rule that does not fire looks exactly like a rule that did not
   help. */
/* ---- DENSITY, WITH NOTHING REMOVED ----------------------------------------
   Measured on CREW at ?sim=1 before touching it: 1654px of content in a 708px
   fold. Every row and gap below is a size change only — no row, door, figure or
   sentence is cut, because the two cuts worth making are both architecture and
   therefore Josiah's:

     RUNNING NOW (212px) is a strict SUBSET of the GAMES tab, verified by
       rendering both — GAMES carries the same two live challenges plus stake,
       dates, FINISHED and OCTOBER, and it is one tap away in the tab bar.
     .rv-head's sentence duplicates the games count above it AND the debt on the
       roster row below it — but ONLY while something is running. On an empty day
       it reads "Nothing running right now. Nobody owes anybody.", which is the
       one line that makes the screen worth opening. Conditional value, so it
       stays; cutting it unconditionally would break the empty case to save 39px.

   Roster rows were 80px for a name, a reliability line and a debt tag. 13px of
   symmetrical padding on a two-line row is a list that has been given a card's
   breathing room; HEAT's person rows run ~56-60. Six of them is where this
   screen's length actually lives. */
/* `.rv-p` was here and matched NOTHING — personRow() emits `.rv-row`, the same
   class as the account rows, so one rule already covered both. Removed. It is the
   second dead selector this pass (see the :first-of-type note above), and both were
   found the same way: the measurement did not move. A CSS rule that does not fire is
   indistinguishable from one that did not help, which is the whole argument for
   measuring the screen rather than reading the stylesheet. */
html[data-look="rivalry"] .rv-row{padding:10px 0}
/* 40px between blocks made sense when each block was a card on its own ground.
   Once the field runs edge to edge the gap is doing a border's job again, and
   four of them is 160px of the scroll. */
html[data-look="rivalry"] .rv-blk{margin-top:28px}
html[data-look="rivalry"] .rv-last{margin-top:24px}


html[data-look="rivalry"] .rv-h2h{
  font-family:var(--disp);font-weight:800;font-stretch:88%;font-size:17px;
  line-height:1;letter-spacing:-.02em;color:var(--t2);
  font-variant-numeric:tabular-nums;white-space:nowrap;
  min-width:42px;text-align:right}
html[data-look="rivalry"] .rv-h2h i{font-style:normal;opacity:.38;margin:0 1px}
html[data-look="rivalry"] .rv-h2h.up{color:var(--green)}
html[data-look="rivalry"] .rv-h2h.dn{color:var(--gold)}
html[data-look="rivalry"] .rv-h2h.new{
  font-family:var(--mono);font-size:8.5px;letter-spacing:.08em;color:var(--t3);
  font-weight:400}
html[data-look="rivalry"] .rv-h2h.me{color:var(--line);font-size:15px}

/* The money steps back. It is real and it stays on the row, but in a direction
   about grudges the scoreline outranks it — and there is a whole MONEY tab. */
html[data-look="rivalry"] .rv-row-v{
  font-family:var(--mono);font-size:11px;font-weight:400;color:var(--t3);
  min-width:52px;text-align:right;letter-spacing:0}

/* The section rule gets the accent, so each block starts with a mark rather
   than a hairline. Small, and it is most of why the screen stops reading as a
   settings page. */
html[data-look="rivalry"] .rv-sec{
  border-bottom-color:var(--line);position:relative}
html[data-look="rivalry"] .rv-sec::after{
  content:"";position:absolute;left:0;bottom:-1px;width:34px;height:2px;
  background:var(--gold)}

@media (prefers-reduced-motion:reduce){
  html[data-look="rivalry"] .rv-hero{transition:none}
}

/* ===========================================================================
   RESTRAINT, THE EDITION — one number, one verb, and nine tenths empty.
   Appended 2026-09-11. Scoped under .rs.

   THE EMPTINESS IS THE DESIGN, not an unfinished screen. Every other direction
   in this app fills the viewport; this one is mostly ground, and the figure is
   large enough that it has to be the only thing you look at. If a second
   element ever earns a place here, the direction has stopped being itself.
   =========================================================================== */
html[data-style="restraint"] .rs-wrap{
  padding:64px 28px 56px;max-width:34rem;margin:0 auto;min-height:72vh;
  display:flex;flex-direction:column}

html[data-style="restraint"] .rs-kick{
  font-family:var(--mono,var(--body));font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--t3)}

/* Instrument Serif at display size is the entire voice of this direction. It
   is the only place in the app where a serif carries a number. */
html[data-style="restraint"] .rs-fig{
  font-family:var(--disp);font-weight:400;font-size:clamp(72px,26vw,128px);
  line-height:.86;letter-spacing:-.035em;color:var(--t1);margin-top:14px;
  font-variant-numeric:tabular-nums}
html[data-style="restraint"] .rs-refuse{
  font-family:var(--disp);font-weight:400;font-size:clamp(34px,10vw,46px);
  line-height:1.08;letter-spacing:-.02em;color:var(--t1);margin:26px 0 0}
html[data-style="restraint"] .rs-say{
  margin:30px 0 0;max-width:30ch;font-size:17px;line-height:1.5;color:var(--t2)}
html[data-style="restraint"] .rs-body{
  margin:22px 0 0;max-width:34ch;font-size:14px;line-height:1.6;color:var(--t3)}

/* THE VERB. One per screen, and it is given a great deal of room on purpose —
   the pause before it is part of the argument. */
html[data-style="restraint"] .rs-verb{
  display:inline-flex;align-items:center;gap:10px;align-self:flex-start;
  margin-top:64px;min-height:48px;padding:0 2px;border:0;background:none;
  font-family:var(--disp);font-weight:400;font-size:25px;letter-spacing:-.01em;
  color:var(--t1);cursor:pointer;border-bottom:1px solid var(--t1);
  transition:opacity var(--d-slow) var(--ease)}
html[data-style="restraint"] .rs-verb:active{opacity:.55}

html[data-style="restraint"] .rs-quiet{margin-top:auto;padding-top:64px}
html[data-style="restraint"] .rs-quiet p{
  margin:0 0 18px;max-width:32ch;font-size:12.5px;line-height:1.6;color:var(--t3)}
html[data-style="restraint"] .rs-link{
  display:block;width:100%;text-align:left;min-height:44px;padding:0;border:0;
  background:none;cursor:pointer;color:var(--t2);
  font-family:var(--body);font-size:14px;
  border-bottom:1px solid var(--line2)}
html[data-style="restraint"] .rs-link:active{color:var(--t1)}

/* The board, when you have earned it. Names and numbers, nothing else — no
   rank column, no avatars, no bars. The position is already the figure above. */
html[data-style="restraint"] .rs-board{margin-top:52px}
html[data-style="restraint"] .rs-row{
  display:flex;align-items:baseline;gap:16px;width:100%;text-align:left;
  padding:15px 0;border:0;border-bottom:1px solid var(--line2);
  background:none;cursor:pointer;color:var(--t2)}
html[data-style="restraint"] .rs-row.you{color:var(--t1)}
html[data-style="restraint"] .rs-n{
  font-family:var(--disp);font-weight:400;font-size:21px;letter-spacing:-.01em;
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
html[data-style="restraint"] .rs-v{
  font-family:var(--body);font-size:14px;font-variant-numeric:tabular-nums;
  color:var(--t3)}
html[data-style="restraint"] .rs-row.you .rs-v{color:var(--t1)}

html[data-style="restraint"] .rs-bug{
  display:flex;align-items:baseline;gap:9px;padding:0 28px;height:100%}
html[data-style="restraint"] .rs-bug span{
  font-family:var(--disp);font-weight:400;font-size:19px;color:var(--t1)}
html[data-style="restraint"] .rs-bug em{
  font-style:normal;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--t3)}

@media (prefers-reduced-motion:reduce){
  html[data-style="restraint"] .rs-verb{transition:none}
}

/* ---- THE MONTH, second pass -----------------------------------------------
   Josiah: "keep going more in-depth on the rivalry section and the month part
   as well. It doesn't look great."

   The fault was the same species as Rivalry's and again it was ORDER, not
   decoration: the hero was "16 holes", a fact about the MONTH, so it sat
   perfectly still while the scrubber moved. This direction's one signature is
   that you can drag through time, and the biggest element on the screen was
   refusing to participate. The date is the hero now and the sentence under it
   reports that day, so the headline moves under your thumb.

   Swiss, so the discipline is: few type sizes, one accent used as a MARK and
   never a fill, a hard rule doing the work a box would do in another direction,
   and tabular figures everywhere a number can change.
   -------------------------------------------------------------------------- */
.mo-head{
  display:block;padding:26px 0 18px;border-bottom:2px solid var(--t1);
  position:relative}
.mo-kick{
  display:block;font-family:var(--mono);font-size:9px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--t3)}
/* The date, and it changes as you drag. Tabular figures so the headline does
   not jitter horizontally while scrubbing — the whole point is that the number
   moves and the layout does not. */
.mo-big{
  font-family:var(--disp);font-weight:700;font-size:clamp(44px,15vw,62px);
  line-height:.92;letter-spacing:-.045em;color:var(--t1);margin:10px 0 0;
  font-variant-numeric:tabular-nums;text-transform:uppercase}
.mo-when{
  display:inline-block;margin-top:12px;padding:3px 7px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;
  background:var(--t1);color:var(--bg)}
/* TODAY is the accent; any other day is ink. The colour is doing work — it
   tells you at a glance whether you are looking at now or at history. */
.mo-when.now{background:var(--gold);color:var(--onGold)}
.mo-head .mo-note{
  margin:16px 0 0;max-width:32ch;font-size:16px;line-height:1.4;color:var(--t1)}

.mo-sub{
  margin:14px 0 0;font-family:var(--mono);font-size:10px;letter-spacing:.04em;
  color:var(--t3);text-transform:uppercase}

/* THE GRID EARNS ITS SPACE. 16px cells read as a sparkline; the month is the
   subject of this direction and has to look like the subject. */
.mo-grid{gap:3px}
.mo-c{height:26px}
.mo-who{font-size:8.5px;width:30px}
.mo-t{font-size:7.5px;padding-bottom:6px}
/* The cursor column is a full-height rule through the whole grid rather than a
   ring on one cell — you are pointing at a DAY, which is a column, not at one
   person's square. */
.mo-c.now{
  box-shadow:inset 0 0 0 2px var(--t1)}
.mo-c.hole.now{
  background:var(--panel2);box-shadow:inset 0 0 0 2px var(--t1)}

/* The bands: day-level readings, tightened so the grid keeps the weight. */
.mo-band{padding:11px 0}
.mo-k{width:58px;font-size:8px}
.mo-v{font-size:14px}
.mo-n{font-size:13px}

.mo-scrub{margin-top:22px}
.mo-drag{color:var(--gold);letter-spacing:.1em}

/* ===========================================================================
   THE GATE, MERGED WITH THE APP — three candidates.
   Added 2026-09-11. Josiah: "the UI doesn't match from the login to the actual
   app and I don't really like how this one feels — try a sort of merge between
   the two."

   THE DIAGNOSIS, measured rather than guessed. It is NOT the palette: the gate
   already wears rivalry's colours, because --field, --raise and the rest are
   indirections over --panel which every direction redefines, and custom
   properties resolve at the point of use. It is SHAPE and COMPOSITION:

     1. `.field input` carries a HARD-CODED `border-radius: 11px`. Every other
        rounded thing in the app is `var(--rad*)`, which rivalry sets to 0 — so
        one literal value leaves the login with soft inputs while the app it
        opens into has none. A single hard-coded number is the whole visual
        discontinuity people feel and cannot name.
     2. `.gate` paints `--hero` across the FULL PAGE, where the app uses that
        gradient for one band at the top. So the login is a warm wash and the
        app is a flat ground with one warm band.
     3. The gate is soft and generous — filled boxes, 52px fields, big gaps.
        The app is dense and hairline-ruled. Same colours, opposite manners.

   All three candidates fix (1) and speak the app's language. They differ in
   composition, which is the axis that actually separates two designs.
   =========================================================================== */

/* Shared by all three: the app's shape language reaches the login. */
html[data-gate] .field input{
  border-radius:var(--rad2);
  font-family:var(--mono);
  font-weight:400;
  letter-spacing:.01em;
}
html[data-gate] .field label{
  font-family:var(--mono);font-weight:400;font-size:9px;letter-spacing:.16em}
html[data-gate] .gate .k{font-family:var(--mono);font-weight:400;letter-spacing:.16em}

/* ---------------------------------------------------------------------------
   A — INSTRUMENT. The login stops being a landing page and becomes the first
   screen of the tool. Flat ground, hairline rules instead of boxes, fields that
   are a labelled line rather than a container. The quietest of the three and
   the most consistent with Restraint as well as Rivalry.
   --------------------------------------------------------------------------- */
html[data-gate="a"] .gate{background:var(--bg);padding:34px 20px 20px}
html[data-gate="a"] .gate h1{
  font-size:34px;line-height:1;letter-spacing:-.04em;text-transform:uppercase;
  margin-top:10px}
html[data-gate="a"] .gate .lede{font-size:13.5px;max-width:34ch;margin-top:14px}
html[data-gate="a"] .gate .promise{
  background:none;border:0;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);border-radius:0;padding:13px 0;margin:22px 0 0}
html[data-gate="a"] .field{margin-top:22px}
/* A field as a RULE, not a box. The app has no boxes; neither does this. */
html[data-gate="a"] .field input{
  background:none;border:0;border-bottom:1px solid var(--line);
  border-radius:0;min-height:46px;padding:0 0 2px;font-size:16px}
html[data-gate="a"] .field input:focus{
  outline:0;border-bottom-color:var(--gold);border-bottom-width:2px}
html[data-gate="a"] .btn{border-radius:0;font-family:var(--mono);font-weight:400;
  font-stretch:100%;letter-spacing:.14em;font-size:12px;min-height:50px}
html[data-gate="a"] .btn.ghost{background:none;border-color:var(--line)}

/* ---------------------------------------------------------------------------
   B — MARQUEE. The app's loudest asset is its display face at hero scale, so
   the login opens with it: the wordmark set the size Rivalry sets a rival's
   name, over a skin rule. The form is compact underneath because the name has
   already done the persuading.
   --------------------------------------------------------------------------- */
html[data-gate="b"] .gate{background:var(--bg);padding:30px 20px 20px}
html[data-gate="b"] .gate .k{color:var(--t3)}
html[data-gate="b"] .gate h1{
  font-size:clamp(44px,15vw,58px);line-height:.88;letter-spacing:-.05em;
  text-transform:uppercase;margin:12px 0 0;font-stretch:100%}
/* The mark under the name is the same 34px accent the app puts under a section
   head — one detail, repeated, is what makes two screens feel authored. */
html[data-gate="b"] .gate h1::after{
  content:"";display:block;width:56px;height:3px;background:var(--gold);
  margin-top:16px}
html[data-gate="b"] .gate .lede{font-size:14px;max-width:30ch;margin-top:16px}
html[data-gate="b"] .gate .promise{
  background:none;border:0;border-left:2px solid var(--gold);border-radius:0;
  padding:4px 0 4px 12px;margin:20px 0 0;font-size:12px}
html[data-gate="b"] .field{margin-top:16px}
html[data-gate="b"] .field input{
  border-radius:0;min-height:48px;background:var(--panel);border-color:var(--line2)}
html[data-gate="b"] .btn{border-radius:0;font-stretch:100%;letter-spacing:.1em;
  min-height:52px}
html[data-gate="b"] .btn.ghost{background:none;border-color:var(--line)}

/* ---------------------------------------------------------------------------
   C — FIELD. Keeps the warmth people liked about the current login, but takes
   it from the app rather than from a full-page wash: the same diagonal colour
   field Rivalry wears behind its hero, one mark in the corner, flat ground
   everywhere else. The only one of the three that previews the app's mechanism.
   --------------------------------------------------------------------------- */
html[data-gate="c"] .gate{
  background:var(--bg);padding:32px 20px 20px;position:relative;overflow:hidden}
html[data-gate="c"] .gate::before{
  content:"";position:absolute;right:-70px;top:-60px;width:230px;height:230px;
  background:var(--gold);opacity:.16;transform:rotate(28deg);pointer-events:none}
html[data-gate="c"] .gate > *{position:relative}
html[data-gate="c"] .gate h1{
  font-size:40px;line-height:.95;letter-spacing:-.045em;text-transform:uppercase;
  margin-top:12px}
html[data-gate="c"] .gate .lede{font-size:14px;max-width:32ch;margin-top:14px}
html[data-gate="c"] .gate .promise{
  background:var(--panel);border:1px solid var(--line2);border-radius:0;
  padding:13px;margin:22px 0 0;font-size:12.5px}
html[data-gate="c"] .field{margin-top:20px}
html[data-gate="c"] .field input{
  border-radius:0;min-height:50px;background:var(--panel);border-color:var(--line)}
html[data-gate="c"] .btn{border-radius:0;font-stretch:100%;letter-spacing:.1em}
html[data-gate="c"] .btn.ghost{background:none;border-color:var(--line)}

/* ---- AN OVERLAY MUST OCCLUDE -----------------------------------------------
   `#l3 .bd` (the lower-third toast) paints `var(--raise)`, which styles.css
   defines as a gradient between --panel2 and --panel. That is opaque in
   Broadcast, where --panel is a solid #0c1f31. In Rivalry --panel is
   `rgba(255,255,255,.045)` — a translucent WASH, which is exactly right for a
   panel resting on the flat ground and exactly wrong for something that has to
   sit on top of content. The toast therefore rendered with almost no backing
   and its text collided with the fixture rows behind it.

   Caught in a screenshot, not by any check: the toast lives for 3.6 seconds, so
   it is only ever seen by somebody looking at the right moment.

   The fix is general rather than per-direction. An opaque BACKGROUND-COLOR of
   the page ground, with --raise kept as the background-IMAGE over it, so every
   direction keeps its own gradient and none of them can be see-through.
   -------------------------------------------------------------------------- */
html[data-style] #l3 .bd{
  background-color:var(--bg);
  background-image:var(--raise);
}

/* ===========================================================================
   ARENA, THE EDITION — the app is a scoreboard, lit in volt.
   Added 2026-09-11. Josiah: "add back that one color way with the electric
   green or whatever it was called."

   It was the emptiest direction in the set — sig: null, a palette and a
   condensed face and no mechanism — so putting it back in the picker meant
   building it. The mechanism is MOVEMENT: every position carries its change
   since yesterday, which is the one thing a scoreboard says that a leaderboard
   does not.

   Volt is a MARK and a fill for one thing at a time. Used everywhere it stops
   meaning anything, and #D8FF3E on a dark ground is loud enough that a little
   is a lot.
   =========================================================================== */
.ar-wrap{padding:0 18px 36px}

.ar-head{padding:20px 0 16px;border-bottom:2px solid var(--gold)}
.ar-kick{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.14em;
  color:var(--t3);text-transform:uppercase}
/* Barlow Condensed at scoreboard size is the entire voice here. */
.ar-title{font-family:var(--disp);font-weight:700;font-size:clamp(38px,12vw,50px);
  line-height:.9;letter-spacing:.005em;text-transform:uppercase;margin:8px 0 0;
  color:var(--t1)}
.ar-meta{display:flex;gap:20px;margin-top:14px}
.ar-meta span{display:flex;flex-direction:column;font-family:var(--mono);
  font-size:8px;letter-spacing:.12em;color:var(--t3);text-transform:uppercase}
.ar-meta b{font-family:var(--disp);font-weight:700;font-size:22px;letter-spacing:0;
  color:var(--t1);font-variant-numeric:tabular-nums;line-height:1.05}

.ar-board{margin-top:4px}
.ar-row{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:13px 0;border:0;border-bottom:1px solid var(--line2);
  background:none;color:var(--t1);cursor:pointer}
.ar-row:active{background:var(--press)}
/* The leader is the only row that gets the fill. One lit row on a dark board is
   what a scoreboard looks like; lighting several is what a dashboard looks
   like. */
.ar-row.lead{background:var(--goldWash);border-bottom-color:var(--gold)}
.ar-pos{font-family:var(--disp);font-weight:700;font-size:26px;line-height:1;
  width:26px;flex:none;text-align:right;font-variant-numeric:tabular-nums;
  color:var(--t2)}
.ar-row.lead .ar-pos{color:var(--gold)}
.ar-row.me .ar-pos{color:var(--t1)}
.ar-mv{font-family:var(--mono);font-size:9px;width:30px;flex:none;
  letter-spacing:.02em}
.ar-mv.up{color:var(--green)}
.ar-mv.dn{color:var(--redDot)}
.ar-mv.flat,.ar-mv.none{color:var(--t3)}
.ar-nm{font-family:var(--disp);font-weight:600;font-size:20px;letter-spacing:.01em;
  text-transform:uppercase;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.ar-row.me .ar-nm{color:var(--gold)}
.ar-tot{font-family:var(--disp);font-weight:700;font-size:21px;
  font-variant-numeric:tabular-nums;white-space:nowrap}

.ar-key{margin-top:12px;font-family:var(--mono);font-size:8px;letter-spacing:.1em;
  color:var(--t3)}
.ar-gap{display:flex;align-items:baseline;gap:8px;margin-top:26px;
  padding-top:16px;border-top:1px solid var(--line);
  font-family:var(--mono);font-size:9px;letter-spacing:.12em;color:var(--t2)}
.ar-gap b{font-family:var(--disp);font-weight:700;font-size:34px;letter-spacing:-.01em;
  color:var(--t1);font-variant-numeric:tabular-nums}
.ar-gap.lead b{color:var(--gold)}

.ar-note{margin:16px 0 0;max-width:32ch;font-size:13px;line-height:1.5;color:var(--t2)}
.ar-act{display:flex;align-items:center;justify-content:center;width:100%;
  min-height:50px;margin-top:26px;border:0;border-radius:var(--radb);
  background:var(--gold);color:var(--onGold);cursor:pointer;
  font-family:var(--disp);font-weight:700;font-size:17px;letter-spacing:.06em;
  text-transform:uppercase}
.ar-act:active{background:var(--gold2)}

.ar-foot{display:flex;flex-wrap:wrap;gap:0 18px;margin-top:30px;
  padding-top:14px;border-top:1px solid var(--line2)}
.ar-link{background:none;border:0;padding:12px 0;min-height:44px;cursor:pointer;
  font-family:var(--mono);font-size:9px;letter-spacing:.12em;color:var(--t3)}
.ar-link:active{color:var(--gold)}

.ar-bug{display:flex;align-items:center;gap:10px;padding:0 18px;height:100%}
.ar-bug-l{font-family:var(--mono);font-size:8px;letter-spacing:.14em;color:var(--t3)}
.ar-bug-n{font-family:var(--disp);font-weight:700;font-size:17px;
  text-transform:uppercase;color:var(--gold)}
.ar-bug-m{margin-left:auto;font-family:var(--mono);font-size:9px;color:var(--green)}

/* ===========================================================================
   THE OTHER SIX, BUILT OUT. Added 2026-09-11.
   Josiah: "bro bring the other ones back, the thing you were supposed to do was
   make all of them reworks and not just retextures."

   Fair. The instruction was "remove the little ui changes AND MAKE THE REWORKS"
   and only the removing half had been done. Each block below carries the
   composition for one direction; the palettes and faces were already measured
   out of the prototypes and are untouched.

   Shared: the doors every edition must carry, dressed per direction.
   =========================================================================== */
.lg-doors,.tm-doors,.rc-doors,.tl-doors,.ps-doors,.ob-doors{
  display:flex;flex-wrap:wrap;gap:0 18px;margin-top:30px;padding-top:14px;
  border-top:1px solid var(--line2)}
.lg-door,.tm-door,.rc-door,.tl-door,.ps-door,.ob-door{
  background:none;border:0;padding:12px 0;min-height:44px;cursor:pointer;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;color:var(--t3);
  text-transform:uppercase}
.lg-door:active,.tm-door:active,.rc-door:active,
.tl-door:active,.ps-door:active,.ob-door:active{color:var(--gold)}

/* ---------------------------------------------------------------------------
   LEDGER — the money is the product. A statement of account: columns, a running
   balance, and performance demoted to an explanation.
   --------------------------------------------------------------------------- */
html[data-look="ledger"] .lg-wrap{padding:22px 20px 36px}
html[data-look="ledger"] .lg-head{padding-bottom:18px;border-bottom:1px solid var(--line)}
html[data-look="ledger"] .lg-kick{font-family:var(--mono);font-size:9px;
  letter-spacing:.16em;color:var(--t3)}
html[data-look="ledger"] .lg-fig{font-family:var(--disp);font-weight:600;
  font-size:clamp(46px,15vw,60px);line-height:1;letter-spacing:-.03em;margin-top:8px;
  font-variant-numeric:tabular-nums;color:var(--t1)}
/* THE COLOUR ARGUMENT, IMPLEMENTED RATHER THAN TOKENED. 1a states it exactly:
   "Red is reserved for LIABILITY - money you owe, days you missed, the overdue
   card. ANYTHING YOU HAVE EARNED IS BONE WHITE."
   So a positive balance is bone, not green. It rendered green - +$140 in mint on
   the home screen - which is this direction congratulating you in colour, and
   refusing to congratulate is its other stated refusal. A negative stays red,
   because that is a liability and red is what red is for.
   This is the distinction I flagged when I left --gold alone: you cannot get this
   argument by pointing an accent token at red, you get it by taking colour AWAY
   from everything that is not a liability. */
html[data-look="ledger"] .lg-fig.up{color:var(--t1)}
html[data-look="ledger"] .lg-fig.dn{color:var(--red)}
/* The signed amounts are set at their own rule further down this file - see
   .lg-v/.lg-d below. A copy up here was DEAD: equal specificity, earlier in the
   file, so the later one won and the +$40 stayed green while this rule sat there
   looking correct. Caught by LOOKING at the render; the contrast sweep passed
   either way, because green and bone both clear on black. */
html[data-look="ledger"] .lg-cols{display:flex;gap:18px;margin-top:16px}
html[data-look="ledger"] .lg-cols span{display:flex;flex-direction:column;
  font-family:var(--mono);font-size:8px;letter-spacing:.1em;color:var(--t3)}
html[data-look="ledger"] .lg-cols b{font-family:var(--disp);font-weight:600;
  font-size:17px;color:var(--t1);font-variant-numeric:tabular-nums;letter-spacing:0}
html[data-look="ledger"] .lg-blk{margin-top:30px}
html[data-look="ledger"] .lg-sec{display:flex;justify-content:space-between;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;color:var(--t3);
  padding-bottom:8px;border-bottom:1px solid var(--line)}
html[data-look="ledger"] .lg-row,html[data-look="ledger"] .lg-line{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;padding:12px 0;
  border:0;border-bottom:1px solid var(--line2);background:none;color:var(--t1);
  cursor:pointer}
html[data-look="ledger"] .lg-n{display:flex;flex-direction:column;gap:2px;flex:1;
  min-width:0;font-family:var(--disp);font-weight:500;font-size:15px}
html[data-look="ledger"] .lg-s{font-family:var(--mono);font-size:9px;color:var(--t3);
  font-weight:400}
/* THE RUNNING BALANCE. Tabular figures and a fixed column, so the eye can run
   down it — which is the only reason to print a balance at all. */
html[data-look="ledger"] .lg-v,html[data-look="ledger"] .lg-d,
html[data-look="ledger"] .lg-b{font-family:var(--mono);font-size:12.5px;
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
/* The unsettled figure, sized to sit under the net without competing with it.
   Red because it is the one number on the screen that is neither earned nor owed -
   and red in this direction means exactly that kind of not-yours-yet. */
/* ---- 02 COUNTERPARTIES ---------------------------------------------------
   Two lines per person: name against amount, then the reason under it with the
   action on the same line. The reason is the part that earns the row - a list
   of names and figures is a balance, and this direction's argument is that the
   money is real BETWEEN PEOPLE, which is a sentence, not a column.

   The name half is the button and the CARD is its own button, so tapping the
   row opens the person and tapping CARD starts the hand-off. One control doing
   both would make the commoner tap the rarer action. */
html[data-look="ledger"] .lg-cp{padding:13px 0;border-bottom:1px solid var(--line2)}
html[data-look="ledger"] .lg-cp-m{display:flex;align-items:baseline;gap:12px;width:100%;
  background:none;border:0;padding:0;text-align:left;cursor:pointer;color:inherit}
html[data-look="ledger"] .lg-cp-m .lg-n{flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-size:16px;font-weight:600;color:var(--t1)}
html[data-look="ledger"] .lg-cp-m .lg-v{font-variant-numeric:tabular-nums;font-size:15px;
  color:var(--t1)}
html[data-look="ledger"] .lg-cp-b{display:flex;align-items:center;justify-content:space-between;
  gap:10px;margin-top:5px;min-height:22px}
html[data-look="ledger"] .lg-cp-b .lg-s{font-size:11.5px;color:var(--t3);font-family:var(--mono)}
html[data-look="ledger"] .lg-cp-b .lg-s.dn{color:var(--red)}
/* The one red control on the screen. Ink is the page ground for the same
   measured reason the exposure bar's is - white fails on seven of the ten
   directions' reds, and --bg passes on all ten. */
html[data-look="ledger"] .lg-card{background:var(--red);color:var(--bg);border:0;
  font:800 9.5px/1 var(--disp);letter-spacing:.14em;padding:7px 12px;cursor:pointer;
  flex:none}

/* ---- 03 A CHALLENGE: the board whose right-hand column is money ----
   Four columns with a declared header, which is also what keeps it structurally
   distinct from rivalry's ranked list - an earlier flat-row version of this board
   was a 0.97 greyscale twin of it. Tabular figures so the money column reads down
   the page as a column rather than as scattered amounts. */
/* THE SLOT RENDERS OUTSIDE THE PADDED WRAPPER, which is the same fact the
   .edb-* block near the bottom of this file records - and that comment closes
   with "it would repeat for every future slot". It did, here, on the next slot
   written after it.

   MEASURED at 390px before the fix: .lgb sat left 0 / right 390 with its parent
   being `.scroll` itself, so "#" and "POSITION" touched the screen edges.
   Worth being exact about, because in a screenshot it reads as the right column
   being CUT OFF and it is not - scrollWidth equalled clientWidth on all four
   header cells and document scrollWidth was 390. Nothing overflowed; there was
   simply no gutter, and the fix is a gutter rather than narrower columns.

   16px, NOT the 20px .edb-* uses: `.pad` is 16px and this direction's hero is
   `14px 16px 0`, so 16 is the edge every other rule on the screen starts from,
   and 03 draws all of them starting together.

   MARGIN, NOT PADDING, because these rows carry the rules. Padding would widen
   each row's border-box and run its underline the full width of the screen
   while the text stayed inset. */
html[data-look="ledger"] .lgb{margin:6px 16px 0}
html[data-look="ledger"] .lgb-h,
html[data-look="ledger"] .lgb-r{display:flex;align-items:baseline;gap:10px;
  padding:12px 0;border-bottom:1px solid var(--line2);width:100%;text-align:left}
html[data-look="ledger"] .lgb-h{padding:0 0 8px;border-bottom:2px solid var(--line);
  font:800 9px/1 var(--disp);letter-spacing:.16em;color:var(--t3)}
html[data-look="ledger"] .lgb-r{background:none;border-left:0;border-right:0;border-top:0;
  color:var(--t1);font-size:15px;cursor:pointer}
html[data-look="ledger"] .lgb-r.me{font-weight:600}
html[data-look="ledger"] .lgb-p{width:26px;flex:0 0 26px;color:var(--t3);font-size:12.5px}
html[data-look="ledger"] .lgb-r.me .lgb-p{color:var(--t2)}
html[data-look="ledger"] .lgb-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* Names in caps, the way 03 sets them - "JOSIAH (YOU)", not "Josiah (you)".
   Done in CSS so the data keeps its real casing for everything else that reads
   it, including the screen reader. Row cells only: the header is already caps
   and would lose its 800 weight to this. */
html[data-look="ledger"] .lgb-r .lgb-n{text-transform:uppercase;font-weight:700;
  letter-spacing:.02em;font-size:14.5px}
/* The figure column is bone, not grey. It is a fact the row is about, not a
   caption on one - and against the money column it is the distance that earned
   the money, so the two read at the same weight. */
html[data-look="ledger"] .lgb-v{width:62px;flex:0 0 62px;text-align:right;
  font-variant-numeric:tabular-nums;color:var(--t1);font-size:13.5px}
html[data-look="ledger"] .lgb-v i{font-style:normal;color:var(--t3);font-size:11px}
html[data-look="ledger"] .lgb-m{width:82px;flex:0 0 82px;text-align:right;
  font-variant-numeric:tabular-nums;font-size:13.5px;color:var(--t1)}
/* Red is liability and nothing else: a row that stands to lose a stake. */
html[data-look="ledger"] .lgb-m.dn{color:var(--red)}

/* YOUR ENTRIES: your own last days on this challenge, with the three states the
   artboard marks - OPEN today, BLANK for a zero, BEST for your high. */
html[data-look="ledger"] .lgb-sec{font:800 9px/1 var(--disp);letter-spacing:.16em;
  color:var(--t3);margin:26px 16px 0;padding-bottom:8px;border-bottom:2px solid var(--line)}
html[data-look="ledger"] .lgb-e{margin:0 16px}
html[data-look="ledger"] .lgb-er{display:flex;align-items:baseline;gap:10px;padding:11px 0;
  border-bottom:1px solid var(--line2);font-size:13.5px}
html[data-look="ledger"] .lgb-ed{width:52px;flex:0 0 52px;color:var(--t3);font-size:11px;
  text-transform:uppercase;letter-spacing:.04em}
html[data-look="ledger"] .lgb-ev{flex:1;min-width:0;color:var(--t1);font-variant-numeric:tabular-nums}
html[data-look="ledger"] .lgb-em{font:800 9px/1 var(--disp);letter-spacing:.14em;color:var(--t2)}
html[data-look="ledger"] .lgb-em.dn{color:var(--red)}

/* ---- 04 THE MONTH: the statement of account ----
   A statement is RULED, not tiled - the same reason this direction has no panel
   fills anywhere. Every separator here is a hairline and every figure is
   tabular, so the columns line up down the page the way a printed statement's
   do. */
html[data-look="ledger"] .lg-month{font-family:var(--disp);font-weight:600;
  font-size:clamp(34px,11vw,44px);line-height:1;letter-spacing:-.025em;margin-top:6px;
  color:var(--t1)}
html[data-look="ledger"] .lg-ev{display:flex;align-items:baseline;gap:10px;
  padding:11px 0;border-bottom:1px solid var(--line2);font-size:13px}
html[data-look="ledger"] .lg-ev:last-child{border-bottom:0}
html[data-look="ledger"] .lg-ed{font-family:var(--mono);font-size:11px;color:var(--t3);
  width:52px;flex:0 0 52px;text-transform:uppercase;letter-spacing:.04em}
html[data-look="ledger"] .lg-et{flex:1;min-width:0;color:var(--t1)}
html[data-look="ledger"] .lg-ea{font-family:var(--mono);font-size:12.5px;
  font-variant-numeric:tabular-nums;text-align:right;width:66px;flex:0 0 66px}
/* Earned is bone, owed is red, and nothing else gets a colour. */
html[data-look="ledger"] .lg-ea.up{color:var(--t1)}
html[data-look="ledger"] .lg-ea.dn{color:var(--red)}
html[data-look="ledger"] .lg-ea.flat{color:var(--t3)}

/* DAYS POSTED. One bar per day, filled or not - a shape rather than a number,
   and deliberately not a percentage, because this direction refuses to average. */
html[data-look="ledger"] .lg-bars{display:flex;gap:2px;align-items:flex-end;
  margin:12px 0 4px;height:34px}
/* Height is set inline from the day's own figure - a blank day is a 4px stub
   rather than nothing, so the gap is visible as a gap rather than as absence. */
html[data-look="ledger"] .lg-bar{flex:1 1 0;min-width:0;background:var(--line2);border-radius:0}
html[data-look="ledger"] .lg-bar.on{background:var(--t1)}
/* Today reads as an edge rather than a fill: the day is not over yet. */
html[data-look="ledger"] .lg-bar.now{outline:1px solid var(--t2);outline-offset:1px}
html[data-look="ledger"] .lg-note{font-size:12px;line-height:1.45;color:var(--t2);margin:8px 0 0}

/* CARRIED FORWARD: the one bordered card on the screen, and red because a debt
   is a liability. The artboard draws it as an OUTLINE on black rather than a red
   fill - red is a mark here, not a ground. */
html[data-look="ledger"] .lg-carry{border:1px solid var(--red);padding:14px 14px 16px;margin-top:22px}
html[data-look="ledger"] .lg-carry .lg-kick.dn{color:var(--red)}
html[data-look="ledger"] .lg-carry-n{font-family:var(--disp);font-weight:600;font-size:19px;
  letter-spacing:-.01em;margin-top:7px;color:var(--t1);font-variant-numeric:tabular-nums}
html[data-look="ledger"] .lg-padb{height:26px}

html[data-look="ledger"] .lg-exp{font-family:var(--mono);font-size:13px;
  color:var(--red);margin-top:6px;letter-spacing:.01em}
html[data-look="ledger"] .lg-d{width:62px;color:var(--t2)}
html[data-look="ledger"] .lg-b{width:66px;color:var(--t1);font-weight:500}
/* BONE, NOT GREEN. "Anything you have earned is bone white" - money owed TO you
   is earned, so it does not get a colour. Only liability does. */
html[data-look="ledger"] .lg-v.up,html[data-look="ledger"] .lg-d.up{color:var(--t1)}
html[data-look="ledger"] .lg-v.dn,html[data-look="ledger"] .lg-d.dn{color:var(--red)}
html[data-look="ledger"] .lg-none{margin:14px 0 0;font-size:13px;color:var(--t2)}
html[data-look="ledger"] .lg-act{display:flex;align-items:center;justify-content:center;
  gap:8px;width:100%;min-height:50px;margin-top:26px;border:1px solid var(--gold);
  border-radius:var(--radb);background:var(--gold);color:var(--onGold);cursor:pointer;
  font-family:var(--disp);font-weight:600;font-size:14px;letter-spacing:.08em}
html[data-look="ledger"] .lg-bug{display:flex;align-items:baseline;gap:9px;
  padding:0 20px;height:100%;font-family:var(--mono);font-size:9px;color:var(--t3)}
html[data-look="ledger"] .lg-bug b{font-family:var(--disp);font-size:16px;
  color:var(--t1)}
html[data-look="ledger"] .lg-bug b.up{color:var(--t1)}
html[data-look="ledger"] .lg-bug b.dn{color:var(--red)}
html[data-look="ledger"] .lg-bug i{margin-left:auto;font-style:normal}

/* ---------------------------------------------------------------------------
   TERMINAL — stdout. No hero, no bands, no cards. The log starts at the top of
   the screen because a log that opens with a summary is a dashboard in mono.
   --------------------------------------------------------------------------- */
html[data-style="terminal"] .tm-wrap{padding:14px 14px 36px;font-family:var(--mono)}
html[data-style="terminal"] .tm-top{display:flex;align-items:baseline;gap:7px;
  font-size:11px;color:var(--t2);padding-bottom:10px;
  border-bottom:1px solid var(--line2)}
html[data-style="terminal"] .tm-prompt{color:var(--gold)}
html[data-style="terminal"] .tm-cmd{color:var(--t1)}
html[data-style="terminal"] .tm-count{margin-left:auto;font-size:9px;color:var(--t3)}
html[data-style="terminal"] .tm-line{display:flex;gap:9px;width:100%;text-align:left;
  padding:9px 0;border:0;border-bottom:1px solid var(--line2);background:none;
  color:var(--t1);cursor:pointer;font-family:var(--mono)}
html[data-style="terminal"] .tm-line:active{background:var(--press)}
html[data-style="terminal"] .tm-no{font-size:10px;color:var(--t3);flex:none;
  font-variant-numeric:tabular-nums}
/* THE LEVEL COLUMN is the mechanism: a log tells you how bad a line is before
   you read it. Fixed width so the messages align down the page. */
html[data-style="terminal"] .tm-lv{font-size:9px;letter-spacing:.06em;width:34px;
  flex:none;font-weight:600}
html[data-style="terminal"] .tm-line.err .tm-lv,html[data-style="terminal"] .tm-lv.err{color:var(--redDot)}
html[data-style="terminal"] .tm-line.warn .tm-lv,html[data-style="terminal"] .tm-lv.warn{color:var(--gold)}
html[data-style="terminal"] .tm-line.ok .tm-lv,html[data-style="terminal"] .tm-lv.ok{color:var(--green)}
html[data-style="terminal"] .tm-line.info .tm-lv,html[data-style="terminal"] .tm-lv.info{color:var(--t3)}
html[data-style="terminal"] .tm-body{display:flex;flex-direction:column;gap:3px;
  min-width:0;flex:1}
html[data-style="terminal"] .tm-k{font-size:8.5px;letter-spacing:.1em;color:var(--t3)}
html[data-style="terminal"] .tm-h{font-size:13px;color:var(--t1);line-height:1.3}
html[data-style="terminal"] .tm-s{font-size:10.5px;color:var(--t2);line-height:1.45}
html[data-style="terminal"] .tm-cmds{display:flex;flex-direction:column;gap:8px;
  margin-top:22px}
html[data-style="terminal"] .tm-cmd-btn{text-align:left;padding:11px 12px;
  min-height:44px;border:1px solid var(--line);background:var(--panel);
  color:var(--gold);font-family:var(--mono);font-size:12px;cursor:pointer;
  border-radius:var(--rad2)}
html[data-style="terminal"] .tm-cmd-btn:active{background:var(--panel2)}
html[data-style="terminal"] .tm-bug{display:flex;align-items:center;gap:9px;
  padding:0 14px;height:100%;font-family:var(--mono)}
html[data-style="terminal"] .tm-bug-h{font-size:12px;color:var(--t1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ---------------------------------------------------------------------------
   RECEIPT — a printed object. Nothing above the tear line is interactive,
   because a receipt does not have buttons on it.
   --------------------------------------------------------------------------- */
html[data-style="receipt"] .rc-wrap{padding:18px 16px 36px}
html[data-style="receipt"] .rc-slip{background:var(--panel);padding:20px 18px 0;
  font-family:var(--mono);position:relative;
  box-shadow:0 1px 0 var(--line2), 0 10px 24px rgba(60,50,35,.10)}
html[data-style="receipt"] .rc-head{text-align:center}
html[data-style="receipt"] .rc-title{font-size:15px;letter-spacing:.28em;
  color:var(--t1)}
html[data-style="receipt"] .rc-sub{font-size:9px;letter-spacing:.14em;
  color:var(--t3);margin-top:7px}
html[data-style="receipt"] .rc-doc{font-size:9px;letter-spacing:.1em;
  color:var(--t3);margin-top:3px}
/* The perforation. A dashed rule is the cheapest, truest signal that this is
   meant to be a piece of paper. */
html[data-style="receipt"] .rc-rule{border-top:1px dashed var(--line);margin:16px 0}
html[data-style="receipt"] .rc-col{display:flex;font-size:8px;letter-spacing:.12em;
  color:var(--t3);padding-bottom:7px}
html[data-style="receipt"] .rc-col span:nth-child(1){width:42px}
html[data-style="receipt"] .rc-col span:nth-child(2){flex:1}
html[data-style="receipt"] .rc-line{display:flex;align-items:baseline;
  padding:7px 0;font-size:12px;color:var(--t1)}
html[data-style="receipt"] .rc-q{width:42px;flex:none;color:var(--t3);font-size:10px;
  font-variant-numeric:tabular-nums}
html[data-style="receipt"] .rc-desc{flex:1;min-width:0;display:flex;
  flex-direction:column;gap:2px;text-transform:uppercase;letter-spacing:.04em}
html[data-style="receipt"] .rc-desc i{font-style:normal;font-size:9px;
  color:var(--t3);letter-spacing:.08em}
html[data-style="receipt"] .rc-amt{font-variant-numeric:tabular-nums;
  white-space:nowrap}
/* A SETTLED LINE IS STRUCK THROUGH, the way a paid docket is marked off. This
   is the mechanism: money that has moved looks different from money that might. */
html[data-style="receipt"] .rc-line.struck{color:var(--t3);
  text-decoration:line-through;text-decoration-thickness:1px}
html[data-style="receipt"] .rc-items.settled{opacity:.85}
html[data-style="receipt"] .rc-none{font-size:11px;letter-spacing:.1em;
  color:var(--t3);text-align:center;padding:8px 0}
html[data-style="receipt"] .rc-tot{display:flex;justify-content:space-between;
  font-size:11px;letter-spacing:.1em;color:var(--t2);padding:5px 0}
html[data-style="receipt"] .rc-tot b{font-size:14px;color:var(--t1);
  font-variant-numeric:tabular-nums}
html[data-style="receipt"] .rc-tot b.up{color:var(--green)}
html[data-style="receipt"] .rc-tot b.dn{color:var(--red)}
html[data-style="receipt"] .rc-tot.grand{border-top:1px solid var(--t1);
  margin-top:6px;padding-top:9px}
html[data-style="receipt"] .rc-tot.grand b{font-size:20px}
html[data-style="receipt"] .rc-fine{font-size:8.5px;line-height:1.6;
  letter-spacing:.08em;color:var(--t3);text-align:center;margin:18px 0 0;
  padding-bottom:18px}
/* The torn edge. A zigzag mask on the bottom of the slip. */
html[data-style="receipt"] .rc-tear{height:10px;margin:0 -18px;
  background:var(--panel);
  -webkit-mask-image:repeating-linear-gradient(135deg,#000 0 7px,transparent 7px 14px);
  mask-image:repeating-linear-gradient(135deg,#000 0 7px,transparent 7px 14px)}
html[data-style="receipt"] .rc-act{display:flex;align-items:center;
  justify-content:center;gap:8px;width:100%;min-height:50px;margin-top:24px;
  border:1px solid var(--t1);background:var(--t1);color:var(--bg);cursor:pointer;
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;
  border-radius:var(--radb)}
html[data-style="receipt"] .rc-bug{display:flex;align-items:baseline;gap:10px;
  padding:0 16px;height:100%;font-family:var(--mono);font-size:9px;
  letter-spacing:.1em;color:var(--t3)}
html[data-style="receipt"] .rc-bug b{margin-left:auto;font-size:14px;color:var(--t1)}

/* ---------------------------------------------------------------------------
   TOLERANCE — every figure with its error. The only direction that declines to
   name a leader.
   --------------------------------------------------------------------------- */
html[data-style="tolerance"] .tl-wrap{padding:22px 20px 36px}
html[data-style="tolerance"] .tl-head{padding-bottom:20px;
  border-bottom:1px solid var(--line)}
html[data-style="tolerance"] .tl-head.refuse{border-bottom-color:var(--gold)}
html[data-style="tolerance"] .tl-kick{font-family:var(--mono);font-size:9px;
  letter-spacing:.16em;color:var(--t3)}
html[data-style="tolerance"] .tl-fig{font-family:var(--disp);font-weight:600;
  font-size:clamp(48px,16vw,64px);line-height:.95;letter-spacing:-.03em;
  margin:8px 0 0;color:var(--t1);font-variant-numeric:tabular-nums}
html[data-style="tolerance"] .tl-fig i{font-style:normal;font-family:var(--mono);
  font-size:14px;color:var(--t3);margin-left:8px;letter-spacing:.06em}
html[data-style="tolerance"] .tl-head.refuse .tl-fig{color:var(--gold)}
html[data-style="tolerance"] .tl-note{margin:14px 0 0;max-width:34ch;font-size:13.5px;
  line-height:1.5;color:var(--t2)}
html[data-style="tolerance"] .tl-blk{margin-top:28px}
html[data-style="tolerance"] .tl-sec{display:flex;justify-content:space-between;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;color:var(--t3);
  padding-bottom:8px;border-bottom:1px solid var(--line)}
html[data-style="tolerance"] .tl-row{display:flex;align-items:center;gap:11px;
  width:100%;text-align:left;padding:12px 0;border:0;
  border-bottom:1px solid var(--line2);background:none;color:var(--t1);cursor:pointer}
html[data-style="tolerance"] .tl-n{display:flex;flex-direction:column;gap:3px;
  width:84px;flex:none;font-family:var(--disp);font-weight:600;font-size:14px}
html[data-style="tolerance"] .tl-src{font-family:var(--mono);font-size:8px;
  letter-spacing:.06em;font-weight:400}
html[data-style="tolerance"] .tl-src.device{color:var(--green)}
html[data-style="tolerance"] .tl-src.typed{color:var(--gold)}
html[data-style="tolerance"] .tl-src.mixed{color:var(--t3)}
/* THE INTERVAL, DRAWN. The bar is not the total — it is the range the reading
   could actually cover, positioned on a shared scale so two overlapping bands
   are visibly overlapping. */
html[data-style="tolerance"] .tl-bar{position:relative;flex:1;height:10px;
  background:var(--track);min-width:0}
html[data-style="tolerance"] .tl-bar i{position:absolute;top:0;bottom:0;
  background:var(--gold);display:block}
html[data-style="tolerance"] .tl-row.me .tl-bar i{background:var(--t1)}
html[data-style="tolerance"] .tl-v{font-family:var(--mono);font-size:12px;
  font-variant-numeric:tabular-nums;width:44px;text-align:right}
html[data-style="tolerance"] .tl-fine{margin:14px 0 0;font-size:11px;line-height:1.5;
  color:var(--t3);max-width:36ch}
html[data-style="tolerance"] .tl-act{display:flex;align-items:center;
  justify-content:center;gap:8px;width:100%;min-height:50px;margin-top:24px;
  border:1px solid var(--gold);background:var(--gold);color:var(--onGold);
  cursor:pointer;font-family:var(--disp);font-weight:600;font-size:13px;
  letter-spacing:.08em;border-radius:var(--radb)}
html[data-style="tolerance"] .tl-bug{display:flex;align-items:baseline;gap:9px;
  padding:0 20px;height:100%;font-family:var(--mono)}
html[data-style="tolerance"] .tl-bug-k{font-size:8.5px;letter-spacing:.12em;
  color:var(--t3)}
html[data-style="tolerance"] .tl-bug b{font-size:13px;color:var(--t1);font-weight:400}

/* ---------------------------------------------------------------------------
   POSITION — the book. Up and down are the only hues, so the sign of the move
   is the only colour on the screen.
   --------------------------------------------------------------------------- */
html[data-style="position"] .ps-wrap{padding:22px 20px 36px}
html[data-style="position"] .ps-head{padding-bottom:18px;
  border-bottom:1px solid var(--line)}
html[data-style="position"] .ps-kick{font-family:var(--mono);font-size:9px;
  letter-spacing:.14em;color:var(--t3)}
html[data-style="position"] .ps-fig{font-family:var(--disp);font-weight:600;
  font-size:clamp(50px,17vw,68px);line-height:.95;letter-spacing:-.04em;
  margin:8px 0 0;color:var(--t1);font-variant-numeric:tabular-nums}
html[data-style="position"] .ps-note{margin:14px 0 0;max-width:34ch;font-size:13.5px;
  line-height:1.5;color:var(--t2)}
html[data-style="position"] .ps-blk{margin-top:28px}
html[data-style="position"] .ps-sec{display:flex;justify-content:space-between;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;color:var(--t3);
  padding-bottom:8px;border-bottom:1px solid var(--line)}
html[data-style="position"] .ps-row{display:grid;
  grid-template-columns:1fr auto 52px;grid-template-rows:auto 3px;gap:6px 10px;
  width:100%;text-align:left;padding:11px 0 9px;border:0;
  border-bottom:1px solid var(--line2);background:none;color:var(--t1);
  cursor:pointer;align-items:baseline}
html[data-style="position"] .ps-n{font-family:var(--disp);font-weight:600;
  font-size:15px;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
html[data-style="position"] .ps-row.me .ps-n{color:var(--gold)}
html[data-style="position"] .ps-px{font-family:var(--mono);font-size:14px;
  font-variant-numeric:tabular-nums}
html[data-style="position"] .ps-mv{font-family:var(--mono);font-size:11px;
  text-align:right;font-variant-numeric:tabular-nums}
html[data-style="position"] .ps-mv.up{color:var(--green)}
html[data-style="position"] .ps-mv.dn{color:var(--red)}
html[data-style="position"] .ps-mv.flat{color:var(--t3)}
html[data-style="position"] .ps-bar{grid-column:1 / -1;height:3px;
  background:var(--track);display:block}
html[data-style="position"] .ps-bar i{display:block;height:100%;
  background:var(--gold);transform-origin:left;
  transition:transform var(--d) var(--ease)}
html[data-style="position"] .ps-row.me .ps-bar i{background:var(--t1)}
html[data-style="position"] .ps-fine{margin:14px 0 0;font-size:11px;line-height:1.5;
  color:var(--t3);max-width:36ch}
html[data-style="position"] .ps-act{display:flex;align-items:center;
  justify-content:center;gap:8px;width:100%;min-height:50px;margin-top:24px;
  border:1px solid var(--gold);background:var(--gold);color:var(--onGold);
  cursor:pointer;font-family:var(--disp);font-weight:600;font-size:13px;
  letter-spacing:.06em;border-radius:var(--radb)}
html[data-style="position"] .ps-bug{display:flex;align-items:baseline;gap:9px;
  padding:0 20px;height:100%;font-family:var(--mono);font-size:9px;color:var(--t3)}
html[data-style="position"] .ps-bug b{font-size:15px;color:var(--t1)}
html[data-style="position"] .ps-bug i{margin-left:auto;font-style:normal;font-size:11px}
html[data-style="position"] .ps-bug i.up{color:var(--green)}
html[data-style="position"] .ps-bug i.dn{color:var(--red)}

/* ---------------------------------------------------------------------------
   OBLIGATION — one sentence, set at reading size. The only direction with no
   standings on the home screen at all.
   --------------------------------------------------------------------------- */
html[data-style="obligation"] .ob-wrap{padding:40px 24px 36px;max-width:34rem;
  margin:0 auto}
html[data-style="obligation"] .ob-kick{font-family:var(--mono);font-size:9px;
  letter-spacing:.18em;color:var(--t3);text-transform:uppercase}
/* THE SENTENCE. Newsreader at 30px is the entire direction — a debt written as
   a line of prose rather than shown as a chip. */
html[data-style="obligation"] .ob-say{font-family:var(--disp);font-weight:400;
  font-size:clamp(26px,8.5vw,33px);line-height:1.22;letter-spacing:-.012em;
  color:var(--t1);margin:18px 0 0;max-width:22ch}
html[data-style="obligation"] .ob-say em{font-style:italic;color:var(--gold)}
html[data-style="obligation"] .ob-rate{margin:18px 0 0;font-size:13px;
  line-height:1.55;color:var(--t2);max-width:32ch}
html[data-style="obligation"] .ob-note{margin:16px 0 0;font-size:13.5px;
  line-height:1.55;color:var(--t2);max-width:30ch}
html[data-style="obligation"] .ob-act{display:inline-flex;align-items:center;
  align-self:flex-start;min-height:48px;margin-top:30px;padding:0 2px;border:0;
  border-bottom:1px solid var(--t1);background:none;cursor:pointer;
  font-family:var(--disp);font-weight:400;font-size:22px;color:var(--t1)}
html[data-style="obligation"] .ob-act.quiet{border-bottom-color:var(--line);
  color:var(--t2);font-size:19px}
html[data-style="obligation"] .ob-blk{margin-top:44px}
html[data-style="obligation"] .ob-sec{font-family:var(--mono);font-size:8.5px;
  letter-spacing:.16em;color:var(--t3);padding-bottom:10px;
  border-bottom:1px solid var(--line2)}
html[data-style="obligation"] .ob-line{display:flex;align-items:baseline;gap:10px;
  width:100%;text-align:left;padding:15px 0;border:0;
  border-bottom:1px solid var(--line2);background:none;cursor:pointer;
  font-family:var(--disp);font-weight:400;font-size:17px;line-height:1.3;
  color:var(--t1)}
html[data-style="obligation"] .ob-line em{font-style:italic;color:var(--gold)}
html[data-style="obligation"] .ob-line i{margin-left:auto;font-style:normal;
  font-family:var(--mono);font-size:10px;color:var(--t3)}
html[data-style="obligation"] .ob-line.plain{color:var(--t2);font-size:16px}
html[data-style="obligation"] .ob-bug{display:flex;align-items:baseline;gap:8px;
  padding:0 24px;height:100%;font-family:var(--disp);font-size:14px;color:var(--t2)}
html[data-style="obligation"] .ob-bug b{color:var(--t1)}
html[data-style="obligation"] .ob-bug i{margin-left:auto;font-style:normal;
  font-family:var(--mono);font-size:9px;color:var(--t3)}

/* ---- THE ACCOUNT DOOR MUST NOT BE CLIPPED OFF THE BAR ----------------------
   Measured at 390px across nine editions: obligation ran 26px past the right
   edge of the channel bar, receipt 10px, terminal 5px. The overflowing element
   is the LAST icon button — which is the account door, the route to settings,
   sign-out and the picker itself. Josiah has already been trapped inside an
   edition once by losing that door; clipping it off the screen is the same
   trap wearing a subtler disguise.

   The cause is not any edition's fault: the "THIS DEVICE" chip is sized by its
   text, and each direction sets that text in a different face at a different
   width. Nine typefaces, nine chip widths, one fixed bar.

   So the chip yields and the icons never do. A truncated crew label costs the
   reader nothing; a missing account button costs them the way out.

   SCOPE CORRECTED 2026-09-14, and the direction it was missing is the one that
   needed it most. The selector was html[data-style] #chan, which matches every
   direction EXCEPT broadcast -- broadcast is :root and carries no data-style
   attribute at all, the same fact this file opens by explaining. So the guard
   had never once run on it, and broadcast wears the widest wordmark in the app
   (125% on Archivo's width axis, 151px). Measured at 390px: #chan scrollWidth
   438 against clientWidth 390, with the LAST icon button -- the account door --
   ending at x=438, forty-eight pixels off the right edge of the phone. Live.
   The trap this rule was written to prevent had been sprung the whole time in
   the one edition the rule could not see.
   -------------------------------------------------------------------------- */
#chan .conn{
  min-width:0;flex-shrink:1;overflow:hidden;white-space:nowrap;
  /* THE ELLIPSIS HERE HAS NEVER ONCE RENDERED, and volt is the first face
     wide enough to prove it. text-overflow does not apply to a flex
     container, and .conn is inline-flex so its dot can sit beside the
     label; the label itself is a bare text node from app.js:274, which
     makes it an ANONYMOUS flex item that no selector can reach. So there
     is nothing for the ellipsis to attach to and the chip cut volt's
     THIS DEVICE through the middle of the V with no mark at all.
     Measured at 390px: 102px of label into the 70px the bar has left once
     the wordmark and the three icons have taken theirs.

     A mask needs no element to hang off, so it works where the ellipsis
     cannot, and it says the same thing: the text keeps going. Left in
     place with it, harmless, for the day the label becomes a span.

     A MASK WAS TRIED HERE AND REVERTED. The reasoning was that fading the
     last 8px only touches padding on a chip that fits -- true of the TEXT
     and false of the element, because a mask takes the background with it.
     board's chip fits perfectly and came back with its panel dissolving at
     the right edge. Eight directions made worse to dress up one. */
  text-overflow:ellipsis}
#chan .iconbtn{flex-shrink:0}

/* ===========================================================================
   THE LOGIN, ANIMATED — "THE DRAW"
   Added 2026-09-12. Josiah, rejecting all three static candidates: "I just feel
   like it feels generic. No animation, no intro. I want some personality."

   He is right and the three candidates deserved it. They differed in
   composition and were all equally MOTIONLESS, and a login with no motion is a
   form. design-craft names motion as the axis that carries the most personality
   and the one generated work never varies — three static layouts was three
   answers to the wrong question.

   THIS IS NOT THE INTRO HE HAD REMOVED. That one was a branded overlay that sat
   ON TOP of a rendered app and delayed it; it is still gone, still behind
   INTRO_ON_LOAD, and should stay that way. This is the login screen arriving as
   itself. Nothing is covered, nothing is delayed, every control is hittable
   from the first frame — the animation runs on elements that are already there
   and already working.

   THE MOTION IS THE THESIS, not decoration. The app's whole idea is "today you
   are against somebody", so the login stages a draw: the field sweeps in
   wearing an opponent's colour, the wordmark WIDENS on Bricolage's variable
   width axis, a rule draws under it, and the form rises last. By the time you
   can type, you have already been shown what the app is about.

   Total 1.45s, and the form is interactive throughout.
   =========================================================================== */

html[data-look="rivalry"] .gate{
  position:relative;overflow:hidden;background:var(--bg);
  padding:34px 20px 20px}

/* 1 — THE FIELD SWEEPS IN. The same diagonal the app's hero wears, so the
   login is not referencing the app, it is the same object arriving. */
html[data-look="rivalry"] .gate::before{
  content:"";position:absolute;right:-70px;top:-70px;
  /* Base is the settled field. Decorative, so even its failure is harmless -
     but it follows the same rule as everything else here. */
  width:250px;height:250px;background:var(--gold);opacity:.18;
  transform:rotate(28deg);
  animation:gateField .9s cubic-bezier(.16,1,.3,1) backwards;
  pointer-events:none}
@keyframes gateField{
  from{opacity:0;transform:rotate(28deg) translate(40px,-40px)}
  to{opacity:.18;transform:rotate(28deg)}
}
html[data-look="rivalry"] .gate > *{position:relative}

/* 2 — THE WORDMARK WIDENS. Bricolage carries a real wdth axis at 75..100 and
   it is already loaded for this direction. Type that physically changes width
   as it settles is a move no other app in this set can make and no static
   mockup can imitate — it is the single most "this was authored" second on the
   screen. */
html[data-look="rivalry"] .gate h1{
  font-size:clamp(38px,13vw,52px);line-height:.9;letter-spacing:-.05em;
  text-transform:uppercase;margin:14px 0 0;
  /* Base is wdth 100 and opacity 1 - the FINISHED state. The keyframe starts
     narrow and transparent and lands here, so if it never plays the wordmark is
     simply already wide and already readable. */
  font-variation-settings:'wdth' 100;
  animation:gateMark 1.05s cubic-bezier(.16,1,.3,1) .05s backwards}
@keyframes gateMark{
  0%  {opacity:0;font-variation-settings:'wdth' 75;letter-spacing:.02em}
  55% {opacity:1}
  100%{opacity:1;font-variation-settings:'wdth' 100;letter-spacing:-.05em}
}

/* 3 — THE RULE DRAWS. Left to right, in the accent, after the name has
   settled. scaleX so it costs no layout. */
html[data-look="rivalry"] .gate h1::after{
  content:"";display:block;width:64px;height:3px;background:var(--gold);
  /* Base is drawn. The keyframe starts at 0 and lands on the base. */
  margin-top:16px;transform-origin:left;
  animation:gateRule .5s cubic-bezier(.16,1,.3,1) .55s backwards}
@keyframes gateRule{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* 4 — EVERYTHING ELSE RISES, staggered. 10px and 40ms apart: enough to read as
   sequence, not enough to feel like waiting. */
/* THE STAGGERED RISE IS GONE AND IT IS NOT COMING BACK IN THIS FORM.
   It was `opacity:0` in the BASE rule with the animation restoring it, plus
   delays up to 1.1s. That is precisely QA #20 in this repository - six board
   rows parked at opacity 0 because `animation ... both` holds the from-state
   through the delay and the animation clock stops when frames stop. The board
   recovered once frames resumed. A LOGIN NOBODY CAN SEE HAS NO RECOVERY: there
   is nothing to scroll, nothing to tap, and no reason for the person to wait.
   Josiah: "it dont work at all now rip."

   The rule that follows from it, and it is already written in this codebase:
   A BASE STYLE MUST BE THE FINISHED STATE. Every animation kept below starts
   from a keyframe and lands on the base, so an animation that never runs leaves
   the screen correct rather than blank. The fades are gone because a fade is
   the one effect that cannot be made safe in pure CSS without a class that
   JavaScript removes - and that lives in app.js, which is not this lane's. */

/* The shape language from candidate C, which was never the problem. */
html[data-look="rivalry"] .gate .k{
  font-family:var(--mono);font-weight:400;letter-spacing:.16em;color:var(--gold)}
html[data-look="rivalry"] .gate .lede{font-size:14px;max-width:32ch;margin-top:16px}
html[data-look="rivalry"] .gate .promise{
  background:none;border:0;border-left:2px solid var(--gold);border-radius:0;
  padding:4px 0 4px 13px;margin:22px 0 0;font-size:12.5px}
html[data-look="rivalry"] .gate .field{margin-top:20px}
html[data-look="rivalry"] .gate .field label{
  font-family:var(--mono);font-weight:400;font-size:9px;letter-spacing:.16em}
html[data-look="rivalry"] .gate .field input{
  border-radius:0;min-height:50px;background:var(--panel);
  border-color:var(--line);font-family:var(--mono);font-weight:400}
html[data-look="rivalry"] .gate .field input:focus{
  outline:2px solid var(--gold);outline-offset:1px}
html[data-look="rivalry"] .gate .btn{
  border-radius:0;font-stretch:100%;letter-spacing:.1em;min-height:52px}
html[data-look="rivalry"] .gate .btn.ghost{background:none;border-color:var(--line)}
/* The press has weight. 52px of button that does not acknowledge a thumb is
   the cheapest way to feel unfinished. */
html[data-look="rivalry"] .gate .btn.primary:active{transform:scale(.985)}

/* REDUCED MOTION IS A FULL STOP, NOT A SLOWDOWN. Everything lands in its final
   state immediately — including the width axis, which is the one people forget
   and which leaves the wordmark stuck condensed if it is missed. */
@media (prefers-reduced-motion:reduce){
  html[data-look="rivalry"] .gate::before{
    animation:none;opacity:.18;transform:rotate(28deg)}
  html[data-look="rivalry"] .gate h1{
    animation:none;opacity:1;font-variation-settings:'wdth' 100}
  html[data-look="rivalry"] .gate h1::after{animation:none;transform:scaleX(1)}
  html[data-look="rivalry"] .gate *{animation:none}
}

/* ---- THE fixtureBoard SLOT ------------------------------------------------
   Four editions replace the ranked rows on the fixture screen and nothing else.
   Shared skeleton so the four read as siblings rather than four unrelated
   tables; each direction's own tokens do the rest, which is why there is no
   per-edition block here beyond the two that need a genuinely different cell.
   -------------------------------------------------------------------------- */
.edb-h{display:flex;gap:10px;align-items:baseline;padding:0 0 7px;
  font-family:var(--mono);font-size:8px;letter-spacing:.12em;color:var(--t3);
  border-bottom:1px solid var(--line2)}
.edb-h span{flex:none}
.edb-h span:nth-child(2){flex:1;min-width:0}
.edb{display:block}
.edb-r{display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  padding:11px 0;border:0;border-bottom:1px solid var(--line2);background:none;
  color:var(--t1);cursor:pointer}
.edb-r:active{background:var(--press)}
.edb-p{width:46px;flex:none;font-family:var(--mono);font-size:12px;color:var(--t2);
  font-variant-numeric:tabular-nums}
.edb-r.me .edb-p{color:var(--gold)}
.edb-n{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;
  font-family:var(--disp);font-weight:600;font-size:15px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.edb-n i{font-style:normal;font-family:var(--mono);font-size:8.5px;
  font-weight:400;color:var(--t3)}
.edb-n2{width:58px;flex:none;font-family:var(--disp);font-weight:600;font-size:13px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.edb-v{width:54px;flex:none;text-align:right;font-family:var(--mono);font-size:12.5px;
  font-variant-numeric:tabular-nums}
.edb-note{margin:12px 0 0;font-size:11.5px;line-height:1.5;color:var(--t3);max-width:36ch}

/* Tolerance: the interval drawn, on a shared scale so two overlapping bands are
   visibly overlapping rather than merely reported as such. */
.edb-bar{position:relative;flex:1;height:9px;background:var(--track);min-width:0}
.edb-bar i{position:absolute;top:0;bottom:0;background:var(--gold);display:block}
.edb-r.me .edb-bar i{background:var(--t1)}

/* Position: price leads, and the sign of the move is the only colour. */
.edb-px{width:58px;flex:none;font-family:var(--mono);font-size:13px;
  font-variant-numeric:tabular-nums}
.edb-mv{width:46px;flex:none;text-align:right;font-family:var(--mono);font-size:11px;
  font-variant-numeric:tabular-nums;color:var(--t3)}
.edb-mv.up{color:var(--green)}
.edb-mv.dn{color:var(--red)}

/* Month: the row IS the days. */
.edb-cells{display:flex;gap:2px;flex:1;min-width:0}
.edb-c{flex:1;min-width:0;height:14px;display:block;background:var(--track)}
.edb-c.hit{background:var(--gold)}
.edb-c.part{background:var(--goldWash);box-shadow:inset 0 0 0 1px var(--gold)}
.edb-c.hole{background:none;box-shadow:inset 0 -1px 0 var(--line2)}
.edb-c.today{box-shadow:inset 0 0 0 1.5px var(--t1)}

/* Receipt: printed, with a rule and a total, because a slip has no leaderboard. */
html[data-style="receipt"] .edb-r.rc-item{font-family:var(--mono)}
html[data-style="receipt"] .edb-n{font-family:var(--mono);font-size:12px;
  letter-spacing:.04em;font-weight:400}
.edb-rule{border-top:1px dashed var(--line);margin:10px 0 0}
.edb-tot{display:flex;justify-content:space-between;align-items:baseline;
  padding:9px 0 0;font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  color:var(--t2)}
.edb-tot b{font-size:16px;color:var(--t1);font-variant-numeric:tabular-nums}

/* Rivalry's board: a gap column instead of a position column, because nobody on
   this board has a position. Your own row is the reference the rest are
   measured from, not a competitor in the list. */
.edb-gap{width:62px;flex:none;font-family:var(--disp);font-weight:800;font-size:15px;
  font-variant-numeric:tabular-nums;color:var(--t2)}
.edb-gap.up{color:var(--green)}
.edb-gap.dn{color:var(--gold)}
.edb-h2h{width:48px;flex:none;text-align:right;font-family:var(--disp);font-weight:800;
  font-size:14px;font-variant-numeric:tabular-nums;color:var(--t2)}
.edb-h2h.up{color:var(--green)}
.edb-h2h.dn{color:var(--gold)}
.edb-h2h.me{color:var(--line)}
.edb-r.rv-you{border-bottom-color:var(--line)}
.edb-r.rv-you .edb-n{color:var(--gold)}

/* THE SLOT RENDERS OUTSIDE THE PADDED WRAPPER. Measured: .edb-h sat at left 0
   against a 390 viewport, with its parent being `.scroll` itself — so "GAP"
   touched the screen edge and the right column was pinned against the other.
   The base rows are padded by a container the slot is not inside, which is a
   fact about where the hook injects rather than anything the boards did wrong,
   and it would repeat for every future slot. Declared once, on the four
   top-level pieces a board can emit. */
.edb-h, .edb-r, .edb-note, .edb-tot{padding-left:20px;padding-right:20px}
.edb-rule{margin-left:20px;margin-right:20px}

/* Rivalry's player record — the live gap, and ONLY the live gap. The month
   head-to-head is already on this screen from the base (screens.js:2230), so
   this block deliberately carries no score and no chip strip: two records on
   one screen is what the first draft did. It sits inside `.pad`, which is why
   there is no padding here - the opposite of the board slot above, which
   injects outside its wrapper. Checked, not assumed. */
.rv-rec{margin-top:16px;border-top:1px solid var(--line);padding-top:13px}
.rv-rec-h{font-family:var(--disp);font-weight:800;font-size:10px;letter-spacing:.14em;
  color:var(--t3);margin-bottom:9px}
.rv-rec-top{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.rv-rec-sc{font-family:var(--disp);font-weight:800;font-size:34px;line-height:1;
  color:var(--t1);font-variant-numeric:tabular-nums}
.rv-rec-sc em{font-style:normal;font-size:13px;letter-spacing:.08em;color:var(--t3);
  margin-left:6px;text-transform:uppercase}
.rv-rec-sc.up{color:var(--green)}
.rv-rec-sc.dn{color:var(--gold)}
.rv-rec-say{margin:8px 0 0;font-size:13px;line-height:1.45;color:var(--t2)}

/* ---- the person-screen records: price, slip, trust ----------------------
   Each shape exists because the greyscale acceptance test measured the first
   versions as three-way IDENTICAL — 95 components each, overlap 1.00, because all
   three were a heading plus four key/value rows plus a paragraph. Different words
   in the same object is the retexture. These are the shapes the directions
   actually claim to be. */
.pr-q-main{display:flex;align-items:flex-end;gap:14px;margin:6px 0 4px}
.pr-q-fig{font-size:34px;font-weight:700;line-height:1;color:var(--gold)}
.pr-q-fig em{font-size:16px;font-style:normal;opacity:.6;margin-left:1px}
.pr-q-mv{font-size:14px;font-weight:700;line-height:1.1;padding-bottom:3px}
.pr-q-mv em{display:block;font-size:10px;font-style:normal;letter-spacing:.07em;
  color:var(--t3);font-weight:400;margin-top:1px}

.rc-items{margin:7px 0 2px}
.rc-item{display:flex;gap:10px;align-items:baseline;padding:2px 0;font-size:12px}
.rc-i-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t2)}
.rc-i-v{flex:0 0 auto}

.ob-cols{display:flex;gap:9px;margin:8px 0 4px}
.ob-col{flex:1 1 0;min-width:0;padding:8px 9px;border:1px solid var(--ln);
  border-radius:var(--rad2);background:var(--c2);opacity:.6}
.ob-col.on{opacity:1}
.ob-c-k{font-size:9px;letter-spacing:.08em;color:var(--t3)}
.ob-c-v{font-size:19px;font-weight:700;line-height:1.15;margin-top:3px}
.ob-c-s{font-size:10px;color:var(--t3);margin-top:1px}
.ob-hist{font-size:11px;color:var(--t3);margin-top:6px}

/* ---- V4 (heatv4): a 10px floor under every label ---------------------------------
   Measured 2026-09-22 on a 390px phone (typefloor.cjs): 90 text elements in
   HEAT ran at 7.5-9.5px -- month tick numbers at 7.5, the hero kicker and the
   month's LEADING / YOUR DAY keys at 8, tab labels and roster initials at 8.5.
   HEAT's own prototype (redo/B-heat.html) never goes below 10px. The shipped
   build got smaller than the direction it was built from, one density pass at
   a time, and the rule for this project is that density is never bought by
   shrinking text until it is hard to read.
   Selector list, not a blanket rule: a blanket `.k{font-size:10px}` would also
   SHRINK any .k that is larger elsewhere. typefloor.cjs diffs every text
   element before and after, and must report zero shrinks. */
html[data-style="heatv4"] .k,
html[data-style="heatv4"] .metacell .l,
html[data-style="heatv4"] .tab span,
html[data-style="heatv4"] .conn,
html[data-style="heatv4"] .tag,
html[data-style="heatv4"] .modeline,
html[data-style="heatv4"] .rv-kick,
html[data-style="heatv4"] .rv-sec,
html[data-style="heatv4"] .rv-sec span,
html[data-style="heatv4"] .rv-r,
html[data-style="heatv4"] .rv-crewname,
html[data-style="heatv4"] .rv-row-s,
html[data-style="heatv4"] .rv-row-debt,
html[data-style="heatv4"] .rv-fx-s,
html[data-style="heatv4"] .rv-sc-l,
html[data-style="heatv4"] .rv-h2h.new,
html[data-style="heatv4"] .mo-when,
html[data-style="heatv4"] .mo-sec,
html[data-style="heatv4"] .mo-kick,
html[data-style="heatv4"] .mo-who,
html[data-style="heatv4"] .mo-t,
html[data-style="heatv4"] .mo-k,
html[data-style="heatv4"] .mo-cap,
html[data-style="heatv4"] .mo-drag,
html[data-style="heatv4"] .mo-key,
html[data-style="heatv4"] .mo-key i,
html[data-style="heatv4"] .mo-sub,
html[data-style="heatv4"] .gate .field label{font-size:10px}
html[data-style="heatv4"] .mo-k{width:64px}

/* ---- V4 (heatv4): the three craft states HEAT was missing --------------------------
   Counted 2026-09-22: no ::selection, no :disabled anywhere, and :focus-visible
   on only the hero and the month scrubber - every other control fell back to
   Chrome's default ring, blue on a red-and-black app. The gate's CONTINUE goes
   disabled while it works and looked identical apart from its label. */
html[data-style="heatv4"] ::selection{background:var(--gold);color:var(--onGold)}
html[data-style="heatv4"] :is(button,a,summary,input,select,[tabindex]):focus-visible{
  outline:2px solid var(--gold);outline-offset:2px}
html[data-style="heatv4"] .btn:disabled{opacity:.5;cursor:default;pointer-events:none}
