/* FP kit — built from kit/[1-9]-*.css. Do not edit here; edit the tier. */
/* ═══ TIER 1 · REFERENCE ═══ raw values. Nothing outside tier 2 may name these.
   Enforced by kit/lint.py: a --ref- name appearing in tier 3 or 4 fails the build.
   (Material 3's boundary, held by the import graph rather than by convention.) */
:root{
  --ref-white:#ffffff;      --ref-black:#101010;
  --ref-grey-70:#3d3d3b;    --ref-grey-50:#6a6a66;    --ref-grey-40:#8e8e8a;
  --ref-line:#e2e0dc;
  --ref-garnet:#8c1d2a;     --ref-roast:180,85,31;
  --ref-face-a:'Instrument Sans',system-ui,-apple-system,sans-serif;
  --ref-face-b:'Archivo',system-ui,sans-serif;
  --ref-ease:cubic-bezier(.2,.75,.3,1);
}

/* ═══ TIER 2 · ROLES ═══ the ONLY tier a livery may touch.
   A livery redefines these custom properties and nothing else. If a livery ever
   needs to name a component class, this tier is missing a role — fix it here.
   The number KIT_JITSU trap 12 asks for: component classes named by a livery = 0. */
:root{
  /* surface */
  --ground:var(--ref-white);
  --ink:var(--ref-black);          /* 19.3:1 on ground */
  --ink-quiet:var(--ref-grey-70);  /* 10.1:1 */
  --ink-meta:var(--ref-grey-50);   /*  5.3:1 — meta only, never body */
  --ink-gone:var(--ref-grey-40);   /* a review that was thrown out */
  --rule:var(--ref-line);

  /* the two hues, one job each */
  --removed:var(--ref-garnet);     /* 7.4:1 — means thrown out. Never decoration. */
  --warmth:var(--ref-roast);       /* light only, as an r,g,b triple. Never carries text. */

  /* voice: A is the studio (every sentence a person wrote), B is the machine (the score, alone) */
  --voice-studio:var(--ref-face-a);
  --voice-machine:var(--ref-face-b);

  /* scale — 7 steps, nothing between, nothing below --t-fine */
  --t-score:27.2vw;  --t-hero:clamp(2.15rem,5.1vw,4.05rem);
  --t-head:clamp(1.85rem,4.2vw,3.05rem); --t-lead:clamp(1.3rem,2.5vw,1.72rem);
  --t-quote:clamp(1.24rem,2.1vw,1.58rem); --t-body:1.09rem; --t-fine:1.02rem;

  /* rhythm */
  --pad:clamp(1.35rem,5vw,5.5rem); --band:clamp(3rem,8vh,5rem);
  --item:clamp(1.7rem,4vh,2.6rem); --measure:40rem;
  --ease:var(--ref-ease);
}

/* ═══ TIER 3 · PRIMITIVES ═══ domain-free layout and text. Roles only.
   SCALE_JITSU trap 2: the layer that scales is the one BELOW the components.
   Every one of these is a NAME, never a cell — they compose rather than multiply. */

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--ground);color:var(--ink);font-family:var(--voice-studio);
     font-size:var(--t-body);line-height:1.55;-webkit-font-smoothing:antialiased;overflow-x:clip}
a{color:inherit}
:focus-visible{outline:2.5px solid var(--removed);outline-offset:4px}

/* structure */
.k-page{max-width:1240px;margin:0 auto;padding:0 var(--pad);position:relative}
.k-band{padding:var(--band) 0}
.k-band--open{padding:clamp(3rem,9vh,6.4rem) 0 clamp(1.4rem,3.4vh,2.4rem)}
.k-band--tight{padding:clamp(2rem,5vh,3rem) 0}
.k-band--head{padding:clamp(2.6rem,8vh,5rem) 0 clamp(2.4rem,6vh,3.6rem)}
.k-top{border-top:1px solid var(--rule)}
.k-measure--wide{max-width:52rem}

/* a measure with a spine beside it — the shape a reading needs, and nothing else */
.k-spine{display:grid;grid-template-columns:minmax(0,var(--measure)) minmax(0,1fr);
  gap:clamp(1rem,4vw,3.5rem);align-items:start}

/* rhythm without per-element margins */
.k-stack > * + *{margin-top:var(--sp,1rem)}
.k-stack--wide{--sp:var(--item)}
.k-flow{display:flex;gap:clamp(1rem,3vw,2.4rem);flex-wrap:wrap;align-items:baseline}
.k-split{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;align-items:baseline}
/* a term beside its definition — adjacent, never flung to opposite edges (DESIGN_JITSU 17a) */
.k-def{display:grid;grid-template-columns:minmax(0,12rem) minmax(0,1fr);gap:.35rem 1.6rem;align-items:baseline}
.k-def > * + *{margin:0}
@media (max-width:640px){.k-def{grid-template-columns:1fr;gap:.15rem 0}}

/* the warm plane — light from beyond the frame, behind everything. Identity surfaces only. */
.k-light{position:relative}
.k-light::before{content:"";position:absolute;z-index:-1;right:-28vw;top:-14vh;width:92vw;height:118%;
  pointer-events:none;background:radial-gradient(closest-side at 62% 42%,
    rgba(var(--warmth),.20), rgba(var(--warmth),.07) 52%, transparent 78%)}

/* text roles — the whole scale, and nothing may set a size outside these */
.k-hero{font-size:var(--t-hero);line-height:1.04;letter-spacing:-.038em;font-weight:500;max-width:19ch}
.k-head{font-size:var(--t-head);line-height:1.07;letter-spacing:-.032em;font-weight:500;max-width:18ch}
.k-lead{font-size:var(--t-lead);line-height:1.3;letter-spacing:-.024em;font-weight:500;max-width:26ch}
.k-lead + *{margin-top:clamp(1.6rem,4vh,2.4rem)}
.k-say{font-size:var(--t-body);color:var(--ink-meta);line-height:1.55;max-width:44ch}
.k-say--wide{max-width:58ch}
.k-fine{font-size:var(--t-fine);color:var(--ink-meta);line-height:1.45}
.k-strong{color:var(--ink);font-weight:600}
.k-link{font-weight:500;text-decoration-color:var(--rule);text-underline-offset:3px}
.k-link:hover{text-decoration-color:var(--removed)}
.k-bare{text-decoration:none;display:block}

/* ═══ TIER 4 · COMPONENTS ═══ FP's domain, skinned over the primitives.
   SCALE_JITSU trap 3: generic kits stall because generic parts cannot absorb domain UI.
   Every part here is a thing only a film reading has. Roles only — no raw values,
   no --ref- names. Enforced by kit/lint.py. */

/* THE SCORE — the one shout. --voice-machine appears here and nowhere else.
   Proportional figures: a standalone number in tabular reads gappy (DESIGN_JITSU L5). */
.fp-score{font-family:var(--voice-machine);font-weight:900;font-variation-settings:'wdth' 125;
  font-variant-numeric:proportional-nums lining-nums;letter-spacing:-.055em;line-height:.74;
  color:var(--ink);display:block}
.fp-score--bleed{font-size:var(--t-score);white-space:nowrap;
  margin-left:calc(-1 * var(--pad));margin-right:calc(-1 * var(--pad));
  margin-top:clamp(1.8rem,5vh,3.4rem)}
.fp-score--inline{font-size:clamp(2.4rem,5vw,3.6rem)}

/* CHROME — identical on every surface, so no page is a stranded island (DESIGN_JITSU N5) */
.fp-top{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:clamp(1.3rem,3vh,2rem) 0 0;flex-wrap:wrap}
.fp-top nav{display:flex;gap:clamp(1rem,2.4vw,1.9rem);align-items:baseline}
.fp-top .fp-mark{font-weight:600;font-size:1.24rem;letter-spacing:-.03em;text-decoration:none}
.fp-top nav a{font-size:var(--t-fine);color:var(--ink-meta);text-decoration:none}
.fp-top nav a:hover{color:var(--ink)}
.fp-top nav a[aria-current]{color:var(--ink);font-weight:600}
.fp-foot{margin-top:var(--band);padding:1.4rem 0 clamp(2.6rem,6vh,3.8rem);
  border-top:1px solid var(--rule);display:flex;justify-content:space-between;
  flex-wrap:wrap;gap:.8rem;font-size:var(--t-fine);color:var(--ink-meta)}

/* THE STRIKE — one expressive move, one meaning: this was removed. */
.fp-struck{text-decoration:none;color:var(--removed);position:relative;white-space:nowrap}
.fp-struck::after{content:"";position:absolute;left:-.03em;right:-.03em;top:.545em;height:.072em;
  background:var(--removed);transform:scaleX(0);transform-origin:left;
  transition:transform .8s var(--ease) .35s}
.go .fp-struck::after{transform:scaleX(1)}

/* A REVIEW — counted holds the left spine; thrown out is pushed right and greyed,
   so POSITION carries the verdict and no label has to. */
.fp-quote{max-width:var(--measure)}
.fp-quote p{font-size:var(--t-quote);line-height:1.36;letter-spacing:-.018em}
.fp-quote cite{display:block;font-style:normal;font-size:var(--t-fine);color:var(--ink-meta);margin-top:.5rem}
.fp-quote--cut{margin-left:auto;margin-right:0;max-width:32rem;text-align:right}
.fp-quote--cut p{font-size:clamp(1.09rem,1.6vw,1.24rem);color:var(--ink-gone)}
.fp-quote--cut cite{color:var(--removed)}
.fp-quote--cut p em{font-style:normal;background-image:linear-gradient(var(--removed),var(--removed));
  background-repeat:no-repeat;background-position:100% .66em;background-size:0% 2px;
  transition:background-size .6s var(--ease)}
.fp-quote--cut.in p em{background-size:100% 2px}
.fp-via{color:var(--ink-gone)}

/* A PLACEMENT — on a right spine, so a reading's spread is scannable straight down */
.fp-placed{margin-bottom:var(--item)}
.fp-at{font-family:var(--voice-machine);font-weight:800;font-variation-settings:'wdth' 108;
  font-variant-numeric:proportional-nums lining-nums;font-size:clamp(1.6rem,3vw,2.3rem);
  letter-spacing:-.03em;line-height:1;color:var(--ink);padding-top:.1rem}
.fp-at span{display:block;font-family:var(--voice-studio);font-size:var(--t-fine);
  font-weight:400;color:var(--ink-meta);letter-spacing:0;margin-top:.3rem}
.fp-placed--cut .fp-at{color:var(--removed)}

/* THE COUNTS — what a reading rests on, tight under the number, never an island */
.fp-counts{margin-top:clamp(.9rem,2.2vh,1.4rem);font-size:var(--t-body);color:var(--ink-meta)}
.fp-counts b{color:var(--ink);font-weight:600}

/* A NOTICE — a reading declaring its own weakness, in the reader's plain sight */
.fp-notice{margin-top:1.1rem;max-width:52ch;font-size:var(--t-body);color:var(--ink-meta);line-height:1.55}

/* A METER — honest by construction: the width IS the value */
.fp-meter{height:7px;background:var(--rule);max-width:19rem;margin-top:.95rem}
.fp-meter i{display:block;height:100%;background:var(--ink);width:0;transition:width 1s var(--ease)}
.go .fp-meter i{width:var(--w)}
.fp-meter--removed i{background:var(--removed)}

/* A GOAL — a slow human thing, with an honest bar */
.fp-goal{margin-bottom:clamp(1.9rem,4.4vh,2.9rem)}
.fp-goal .fp-goal-t{font-size:clamp(1.28rem,2.3vw,1.66rem);font-weight:600;letter-spacing:-.024em;line-height:1.2}
.fp-goal--lead .fp-goal-t{font-size:clamp(1.55rem,3.2vw,2.25rem)}
.fp-goal p{max-width:52ch;margin-top:.35rem;color:var(--ink-meta);line-height:1.55}

/* A FILM in the index */
.fp-film{display:block;text-decoration:none;margin-bottom:clamp(2rem,5vh,3.2rem)}
.fp-film-t{display:block;font-size:var(--t-lead);font-weight:600;letter-spacing:-.024em;margin-top:.55rem}
.fp-film-m{display:block;margin-top:.3rem}
.fp-vow{font-size:clamp(1.36rem,2.6vw,1.94rem);line-height:1.24;letter-spacing:-.028em;
  font-weight:500;color:var(--ink);max-width:24ch}
.fp-vow em{font-style:normal;color:var(--removed)}

@media (max-width:800px){
  .fp-score--bleed{font-size:clamp(4.6rem,26vw,9rem)}
  .k-spine{grid-template-columns:1fr;gap:.6rem}
  .fp-at{padding-top:0}
}
@media (prefers-reduced-motion:reduce){
  .fp-struck::after,.fp-quote--cut p em,.fp-meter i{transition:none}
}

/* ═══ LIVERY · PRINT ═══ the boundary test, per KIT_JITSU trap 12.
   Roles only. Zero component selectors. If this file ever names a component,
   the role tier failed and the kit has a ceiling. */
@media print{
  :root{
    --ground:#ffffff; --ink:#000000; --ink-quiet:#222222; --ink-meta:#444444;
    --ink-gone:#666666; --rule:#bbbbbb; --removed:#000000; --warmth:255,255,255;
    --t-score:5.5rem; --t-hero:2rem; --t-head:1.6rem; --t-lead:1.2rem;
    --t-quote:1.05rem; --t-body:.95rem; --t-fine:.85rem;
    --pad:0; --band:1.4rem; --item:.9rem;
  }
}

/* The same roles, selectable, so the bench can render both liveries at once.
   Still roles only — a livery that names a component class fails kit/lint.py. */
[data-livery="print"]{
  --ground:#ffffff; --ink:#000000; --ink-quiet:#222222; --ink-meta:#444444;
  --ink-gone:#666666; --rule:#bbbbbb; --removed:#000000; --warmth:255,255,255;
  --t-score:5.5rem; --t-hero:2rem; --t-head:1.6rem; --t-lead:1.2rem;
  --t-quote:1.05rem; --t-body:.95rem; --t-fine:.85rem; --band:1.4rem; --item:.9rem;
}
