/* glass.css: THE KIT'S TEXT-SURFACE SYSTEM, "the colour and texture of words" (6 Nov 2026). Page-agnostic.
 * Sim: "text that sits in that section ... on translucent glass that can be sized dynamically ... whenever it's my read it needs
 * to be highlighted in gold with your green, and whenever it's other text it needs to be highlighted somehow else."
 *
 * CLASS NAMES (fixed; used by page captions AND by text inside shots, charts and bespoke):
 *   .ts            the base surface: frosted glass (backdrop blur + saturate, solid fallback), sizes to its words
 *                  (inline-size:fit-content; max-inline-size:min(68ch,92%)), padding and radius scale with the container
 *                  (cqi: inside a shot that is the stage; elsewhere the viewport), a soft lifting shadow, a bright top edge.
 *   .ts--read      Sim's read. Deep forest-green glass with a faint gold inner glow, a POLISHED OLD-GOLD rim with a slow travelling
 *                  highlight, cream text, a small polished-gold plate label.   Label text comes from markup: <span class="ts__label">My read</span>
 *                  (or "Sim's read" where the words are in Scarlet's or the third person).
 *   .ts--fact      data and explanation (also the default with no modifier): navy glass, ice-blue hairline rim, cream text,
 *                  optional small ice label ("The data", "How it works").
 *   .ts--note      guardrails and compliance lines: graphite glass, champagne hairline, "Note" label, slightly smaller type; calm.
 *   .ts--source    sources and as-of lines: no glass; quiet mono small caps, low contrast but AA on the navy grounds.
 *   .ts--light     the cream close: ivory marble glass, gold rim for reads, sage for facts, dark ink. Added automatically under
 *                  any [data-era="light"] ancestor, or set it by hand.
 *   Markup:  <p class="ts ts--read"><span class="ts__label">My read</span><span class="ts__text">words</span></p>
 *            (the label is optional on every variant; the text span is optional: bare text works). Alignment: --ts-align:center|start.
 *   Tokens (override on the surface or any ancestor):  --ts-ink, --ts-fill, --ts-fill-solid, --ts-rim (a gradient), --ts-pad-x, --ts-pad-y,
 *            --ts-radius, --ts-blur. Material values are --mat-* so the kit's materials library can take them over.
 *   Layout hooks are :where() (zero specificity): a page may set padding, margins or sizes on its own class and win.
 *   Entry: on the page (outside compositions) a surface rises and fades in when its section gets .is-near (the reel's near-view class).
 *          Inside a composition [data-composition-id] the SHOT's timeline owns opacity and transform (data-at / beats): this file never
 *          animates them there. The rim highlight and sheen are CSS-only and slow (14 s, 11 s); both stop under prefers-reduced-motion.
 *   Degrades: no backdrop-filter = a solid card; no JS = visible; present mode flattens captions into the presenter's own styling.
 *   Budget: one backdrop-filter per surface (keep three or fewer on screen), two pseudo-elements, no JS.
 *   Legacy: .xg-card / data-glass from the first pass are gone; compose.py caption_html() writes the .ts markup. */
:root{
  --mat-gold-ramp:#fff3d6,#f3d9a0 22%,#d9b46a 44%,#8f6d31 66%,#f0d594 84%,#b08a45;     /* polished old gold, lit from above */
  --mat-gold-rim:linear-gradient(160deg,var(--mat-gold-ramp));
  --mat-gold-spec:linear-gradient(105deg,transparent 40%,rgba(255,250,235,.9) 50%,transparent 60%);
  --mat-gold-plate:linear-gradient(150deg,#fff3d6 0%,#e6c887 30%,#b08a45 62%,#e9d093 100%);
  --mat-gold-ink:#2a1d08;
  --mat-ice-rim:linear-gradient(160deg,rgba(216,240,255,.7),rgba(159,214,255,.16) 50%,rgba(159,214,255,.4));
  --mat-champagne-rim:linear-gradient(160deg,rgba(240,226,196,.55),rgba(240,226,196,.1) 50%,rgba(240,226,196,.3));
  --mat-sage-rim:linear-gradient(160deg,rgba(176,206,182,.7),rgba(143,176,150,.16) 50%,rgba(143,176,150,.4));
  --mat-glass-edge:rgba(255,248,225,.5);
  --ts-cream:#eef2f6;
}

/* ---------------------------------------------------------------- the base surface (default look = fact) */
.ts,.x-capstack > .x-voice{
  --ts-ink:var(--ts-cream);
  --ts-fill:rgba(11,18,38,.5);--ts-fill-solid:rgba(11,18,38,.9);
  --ts-rim:var(--mat-ice-rim);--ts-blur:16px;
  --ts-label-ink:#bfe3ff;
  position:relative;display:grid;justify-items:var(--ts-align,start);gap:.5em;align-content:start;box-sizing:border-box;
  color:var(--ts-ink);text-shadow:none;text-wrap:pretty;
  background:var(--ts-fill-solid);
  box-shadow:inset 0 1px 0 var(--mat-glass-edge),inset 0 -14px 28px -18px rgba(216,240,255,.08),0 18px 44px -22px rgba(0,0,0,.65);
  overflow:hidden;isolation:isolate;
}
:where(.ts,.x-capstack > .x-voice){
  inline-size:fit-content;max-inline-size:min(68ch,92%);margin-inline:auto;
  padding:clamp(.55em,1.7cqi,1.05em) clamp(.85em,2.8cqi,1.5em) clamp(.6em,1.8cqi,1.1em);
  border-radius:clamp(10px,1.5cqi,16px);
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .ts,.x-capstack > .x-voice{background:var(--ts-fill);-webkit-backdrop-filter:blur(var(--ts-blur)) saturate(1.35);backdrop-filter:blur(var(--ts-blur)) saturate(1.35)}
}
/* the rim: a hairline drawn with a mask so the glass stays see-through; the variant sets --ts-rim */
.ts::before,.x-capstack > .x-voice::before{
  content:"";display:block;position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;z-index:2;
  background:var(--ts-rim);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);
}
/* the sheen: one soft highlight crossing the glass every ~11 s */
.ts::after,.x-capstack > .x-voice::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:1;
  background:linear-gradient(105deg,transparent 38%,rgba(255,243,214,.13) 50%,transparent 62%) 120% 0/260% 100% no-repeat;
  animation:ts-sheen 11s cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes ts-sheen{0%,12%{background-position:120% 0}58%,100%{background-position:-40% 0}}
@keyframes ts-glint{0%,10%{background-position:130% 0,0 0}50%,100%{background-position:-60% 0,0 0}}
.ts__text,.ts > *,.x-capstack > .x-voice > *{position:relative;z-index:3}
.ts__text{display:block;margin:0}
.ts > p,.ts > ul,.ts > ol{margin:0}
.ts > :where(p,ul,ol) + :where(p,ul,ol){margin-top:.6em}

/* the label: a small mark of what kind of words these are (fact: ice mono; read: a polished gold plate; note: champagne) */
.ts__label{
  position:relative;z-index:3;display:inline-block;
  font:600 .54em/1 var(--o-reel-mono,var(--x-mono,ui-monospace,Menlo,monospace));letter-spacing:.2em;text-transform:uppercase;
  color:var(--ts-label-ink);
}

/* ---------------------------------------------------------------- READ: Sim's voice, forest green with polished gold */
.ts--read{
  --ts-fill:rgba(12,44,34,.6);--ts-fill-solid:rgba(11,38,30,.93);
  --ts-rim:var(--mat-gold-rim);--ts-label-ink:var(--mat-gold-ink);
  background-image:radial-gradient(120% 140% at 0% 0%,rgba(243,217,160,.16),rgba(243,217,160,0) 60%),radial-gradient(90% 120% at 100% 100%,rgba(47,107,82,.34),rgba(47,107,82,0) 70%);
  box-shadow:inset 0 1px 0 rgba(255,248,225,.7),inset 0 0 38px -14px rgba(243,217,160,.35),0 18px 44px -22px rgba(0,0,0,.65);
}
.ts--read::before{
  background:var(--mat-gold-spec) 130% 0/300% 100% no-repeat,var(--mat-gold-rim);
  animation:ts-glint 14s cubic-bezier(.4,0,.2,1) infinite;
}
.ts--read > .ts__label{
  padding:.34em .62em .3em;border-radius:999px;background:var(--mat-gold-plate);
  box-shadow:0 1px 0 rgba(255,250,235,.8) inset,0 -1px 0 rgba(110,83,38,.5) inset,0 2px 8px -2px rgba(0,0,0,.5);
}

/* ---------------------------------------------------------------- FACT: navy glass, ice-blue hairline (the default; the class is for clarity) */
.ts--fact{}

/* ---------------------------------------------------------------- NOTE: guardrails, calm graphite and champagne */
.ts--note{
  --ts-fill:rgba(24,24,28,.62);--ts-fill-solid:rgba(24,24,28,.92);--ts-rim:var(--mat-champagne-rim);--ts-label-ink:#ecdcb6;--ts-blur:14px;
  font-size:.9em;
  box-shadow:inset 0 1px 0 rgba(255,244,214,.3),0 14px 34px -22px rgba(0,0,0,.7);
}
.ts--note::after{opacity:.5}

/* ---------------------------------------------------------------- SOURCE: no glass, quiet mono small caps */
.ts--source{
  background:none !important;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;overflow:visible;padding:0;border-radius:0;
  font:500 .72em/1.5 var(--o-reel-mono,var(--x-mono,ui-monospace,Menlo,monospace));letter-spacing:.14em;text-transform:uppercase;
  color:rgba(233,237,242,.66);
}
.ts--source::before,.ts--source::after{display:none}

/* ---------------------------------------------------------------- LIGHT: the cream close, ivory marble glass */
.ts--light,[data-era="light"] .ts{
  --ts-ink:#16101e;--ts-fill:rgba(255,251,240,.6);--ts-fill-solid:rgba(250,244,230,.94);--ts-label-ink:#4f6f5a;
  --ts-rim:var(--mat-sage-rim);
  background-image:linear-gradient(112deg,transparent 58%,rgba(176,138,69,.12) 58.3%,transparent 59%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),0 16px 36px -24px rgba(80,60,20,.45);
}
.ts--light.ts--read,[data-era="light"] .ts--read{--ts-rim:var(--mat-gold-rim);--ts-label-ink:var(--mat-gold-ink);
  background-image:radial-gradient(110% 130% at 0% 0%,rgba(143,176,150,.3),rgba(143,176,150,0) 62%),linear-gradient(112deg,transparent 58%,rgba(176,138,69,.16) 58.3%,transparent 59%)}
.ts--light.ts--note,[data-era="light"] .ts--note{--ts-rim:var(--mat-champagne-rim);--ts-label-ink:#7a5a1c}
.ts--light.ts--source,[data-era="light"] .ts--source{color:rgba(22,16,30,.62);background:none !important}
.ts--light::after,[data-era="light"] .ts::after{background-image:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.55) 50%,transparent 62%)}

/* ---------------------------------------------------------------- captions on the page: centred, a touch smaller than the old bare line */
.o-shot__caption .ts{--ts-align:center;text-align:center;font-size:.8em}
.o-shot__caption:has(.ts){padding-bottom:clamp(10px,2svh,22px) !important}
.x-capstack > .x-voice{--ts-align:center;text-align:center;max-inline-size:min(40em,100%)}
.x-capstack > .x-voice .x-voice__who{font-size:.54em}

/* ---------------------------------------------------------------- entry: on the page only (a shot's timeline owns its own surfaces) */
@media (prefers-reduced-motion:no-preference){
  html.o-reel-js section.o-shot .o-shot__caption .ts{
    transition:opacity 1s cubic-bezier(.2,.6,.2,1) .3s,transform 1.2s cubic-bezier(.2,.6,.2,1) .3s,filter 1s cubic-bezier(.2,.6,.2,1) .3s;
  }
  html.o-reel-js section.o-shot:not(.is-near) .o-shot__caption .ts{opacity:0;transform:translateY(14px) scale(.985);filter:blur(4px)}
}
@media (prefers-reduced-motion:reduce){
  .ts::after,.x-capstack > .x-voice::after{animation:none;opacity:0}
  .ts--read::before{animation:none}
}

/* present mode: the stage owns the frame; a caption dissolves into the presenter's own styling */
html.is-present .o-shot__caption .ts{background:none;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;padding:0;overflow:visible;background-image:none}
html.is-present .o-shot__caption .ts::before,html.is-present .o-shot__caption .ts::after,html.is-present .o-shot__caption .ts__label{display:none}
html.is-present .x-capstack > .x-voice{background:rgba(5,3,8,.55);overflow:visible}
html.is-present .x-capstack > .x-voice::before,html.is-present .x-capstack > .x-voice::after{display:none}

@media (max-width:600px){
  .o-shot__caption .ts{font-size:.9em}
  :where(.ts,.x-capstack > .x-voice){padding:clamp(.5em,1.6cqi,.7em) clamp(.7em,2.6cqi,1em)}
}
@media print{.ts{background:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.ts::before,.ts::after{display:none}}
