@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&family=Oswald:wght@500;600;700&family=Spectral:wght@500;600&display=swap');

/* =========================================================================
   Doppio bar-chart themes
   One stylesheet, many looks. Every theme targets the existing contract DOM
   (#header / #bars / .bar / #valshapeN / .value / #labels / .barlabel) and is
   scoped under a class on #root, so switching style = swapping that class.
   No HTML changes. Bar colours still come from the palette picker; scripts.js
   also mirrors each colour into --bar-color for tints/glows.
   Sizing uses container-query units so the chart scales to whatever box it is
   injected into (a small thumbnail or a full 1080p slide).

   Loaded AFTER styles.css; #root-scoped selectors win on specificity for the
   chart, while styles.css continues to own the vote-cover overlay.
   ========================================================================= */

/* Registered so arc sweeps (Rainbow) animate smoothly. scripts.js mirrors each
   bar's height %% into --val on the .bar element. */
@property --val {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

/* ---- shared base (all themes) ---- */
#root {
  height: 100%;
  container-type: size;
  container-name: chart;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  --fg: #16161c;            /* primary text (header, labels, on-chart values) */
  --fg-soft: #5a5a66;       /* secondary text */
  --rule: rgba(20, 20, 35, .12);
  --track: rgba(20, 20, 35, .06);
  --chip: #eef0f3;
}
/* light text for dark / image backgrounds */
#root.on-dark {
  --fg: #ffffff;
  --fg-soft: rgba(255, 255, 255, .72);
  --rule: rgba(255, 255, 255, .22);
  --track: rgba(255, 255, 255, .12);
  --chip: rgba(255, 255, 255, .15);
}

#root .wrapper { height: 100%; display: flex; flex-direction: column; box-sizing: border-box; }
#root #header { text-align: center; }
#root #bars { flex: 1 1 auto; min-height: 0; display: flex; align-items: flex-end; }
#root .equalsize { flex: 1 1 0; min-width: 0; }
#root #bars .equalsize { height: 100%; }
#root .proportion { position: relative; height: 100%; width: 100%; }
#root .bar {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0 auto;
  height: 0; box-sizing: border-box; will-change: height;
  transition: height .5s cubic-bezier(.22, .61, .36, 1);
}
#root .valbg { box-sizing: border-box; }
#root #labels { display: flex; }
/* width:auto neutralises styles.css `.barlabel { width:100% }`, which otherwise
   forces the pill-style legends (Pop/Fan/Rainbow, flex:0 0 auto) to full width */
#root .barlabel { flex: 1 1 0; width: auto; min-width: 0; text-align: center; box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; }
#root .value { font-variant-numeric: tabular-nums; }
/* per-vote unit tiles (Blocks theme) — injected by the driver, hidden elsewhere */
#root .units { display: none; }

/* =========================================================================
   01 · POLISHED CLASSIC — refined floating value badge, soft depth
   ========================================================================= */
#root.t-classic .wrapper { padding: 3.5cqh 4cqw 2.6cqh; }
#root.t-classic #header { font-size: clamp(16px, 5.4cqw, 60px); font-weight: 700; color: var(--fg); letter-spacing: .01em; }
#root.t-classic #bars { gap: 3cqw; padding-top: 7cqh; padding-bottom: 1.8cqh; }
#root.t-classic .bar {
  width: 66%; border-radius: 2.6cqw 2.6cqw .8cqw .8cqw;
  box-shadow: 0 1.6cqh 2.6cqh -1.4cqh rgba(20, 20, 35, .4);
}
#root.t-classic .bar::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 44%);
  pointer-events: none;
}
#root.t-classic .valbg {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  width: 11.5cqw; height: 11.5cqw; min-width: 44px; min-height: 44px; border-radius: 50%;
  background: #fff; border: 2px solid #fff;
  box-shadow: 0 1cqh 2.2cqh -.6cqh rgba(20, 20, 35, .32);
  display: flex; align-items: center; justify-content: center;
}
#root.t-classic .value { font-size: clamp(13px, 3.6cqw, 40px); font-weight: 700; color: #16161c; }
#root.t-classic #labels { gap: 3cqw; margin-top: 2cqh; padding-top: 1.7cqh; border-top: 1px solid var(--rule); }
#root.t-classic .barlabel { font-size: clamp(10px, 2.3cqw, 22px); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-soft); }

/* =========================================================================
   02 · BOLD FLAT — big numerals above, flat bars, a hard baseline
   ========================================================================= */
#root.t-flat .wrapper { padding: 3.5cqh 4.2cqw 2.6cqh; }
#root.t-flat #header { font-size: clamp(16px, 5.6cqw, 62px); font-weight: 800; color: var(--fg); letter-spacing: -.01em; }
#root.t-flat #bars { gap: 2.4cqw; padding-top: 9cqh; border-bottom: 3px solid var(--fg); }
#root.t-flat .bar { width: 86%; border-radius: 2.2cqw 2.2cqw 0 0; }
#root.t-flat .valbg {
  position: absolute; left: 50%; top: auto; bottom: 100% !important; transform: translateX(-50%);
  margin-bottom: .8cqh; white-space: nowrap;
  width: auto; height: auto; min-width: 0; min-height: 0;
  /* chip behind the numeral (same surface as the labels below) so the figure
     stays readable over busy slide backgrounds */
  background: var(--chip); border: 0; box-shadow: none;
  border-radius: 1cqw; padding: .7cqh 1.6cqw;
}
#root.t-flat .value { font-size: clamp(12px, calc(6.2cqw * 4 / var(--nopt, 4)), 70px); font-weight: 800; color: var(--fg); line-height: 1; }
#root.t-flat #labels { gap: 2.4cqw; margin-top: 2cqh; }
#root.t-flat .barlabel {
  font-size: clamp(11px, 2.5cqw, 22px); font-weight: 700; color: var(--fg);
  background: var(--chip); border-radius: .9cqw; padding: 1.1cqh 1.6cqw;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* =========================================================================
   03 · CAPSULE ON TRACK — pill bars in a faint 100% track, riding token
   ========================================================================= */
#root.t-capsule .wrapper { padding: 3.5cqh 4cqw 2.6cqh; }
#root.t-capsule #header { font-size: clamp(16px, 5.2cqw, 58px); font-weight: 700; color: var(--fg); }
#root.t-capsule #bars { gap: 3.4cqw; padding-top: 7cqh; padding-bottom: 1.4cqh; }
#root.t-capsule .proportion::before {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%); bottom: 0;
  width: 48%; height: 100%; border-radius: 999px; background: var(--track);
}
#root.t-capsule .bar {
  width: 48%; min-height: 12cqw; border-radius: 999px;
  box-shadow: 0 1.2cqh 2.2cqh -1.2cqh rgba(20, 20, 35, .35);
  transition: height .6s cubic-bezier(.34, 1.18, .5, 1);
}
#root.t-capsule .valbg {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  width: 10cqw; height: 10cqw; min-width: 40px; min-height: 40px; border-radius: 50%;
  background: #fff; box-shadow: 0 1cqh 2.2cqh -.7cqh rgba(20, 20, 35, .32);
  display: flex; align-items: center; justify-content: center;
}
#root.t-capsule .value { font-size: clamp(12px, 3.2cqw, 34px); font-weight: 700; color: #16161c; }
#root.t-capsule #labels { gap: 3.4cqw; margin-top: 2.2cqh; }
#root.t-capsule .barlabel { font-size: clamp(11px, 2.4cqw, 22px); font-weight: 600; color: var(--fg-soft); }

/* =========================================================================
   04 · GLASS DEPTH — gradient + specular highlight + palette-tinted glow
   ========================================================================= */
#root.t-glass .wrapper { padding: 3.5cqh 4cqw 2.6cqh; }
#root.t-glass #header { font-size: clamp(16px, 5.2cqw, 58px); font-weight: 700; color: var(--fg); }
#root.t-glass #bars { gap: 3.4cqw; padding-top: 7.5cqh; padding-bottom: 1.6cqh; }
#root.t-glass .bar {
  width: 62%; border-radius: 3cqw 3cqw 1.2cqw 1.2cqw;
  box-shadow:
    0 2.4cqh 4cqh -1.4cqh color-mix(in srgb, var(--bar-color, #888) 62%, transparent),
    0 .8cqh 1.6cqh -1cqh rgba(20, 20, 35, .35);
}
#root.t-glass .bar::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, .04) 40%, rgba(0, 0, 0, .18));
  pointer-events: none;
}
#root.t-glass .bar::after {
  content: ""; position: absolute; left: 10%; right: 10%; top: 6%; height: 30%;
  border-radius: 1.6cqw; background: linear-gradient(180deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, 0));
  pointer-events: none;
}
#root.t-glass .valbg {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  width: 11cqw; height: 11cqw; min-width: 44px; min-height: 44px; border-radius: 50%;
  background: rgba(255, 255, 255, .58); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .75); box-shadow: 0 1cqh 2.4cqh -.7cqh rgba(20, 20, 35, .3);
  display: flex; align-items: center; justify-content: center; z-index: 2;
}
#root.t-glass .value { font-size: clamp(13px, 3.4cqw, 38px); font-weight: 700; color: #16161c; }
#root.t-glass #labels { gap: 3.4cqw; margin-top: 2.2cqh; }
#root.t-glass .barlabel { font-size: clamp(10px, 2.3cqw, 22px); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--fg-soft); }

/* =========================================================================
   05 · EDITORIAL GRID — quartile gridlines + tabular serif numerals
   ========================================================================= */
#root.t-editorial .wrapper { padding: 3.4cqh 4.4cqw 2.6cqh; }
#root.t-editorial #header {
  text-align: left; font-family: "Spectral", Georgia, serif;
  font-size: clamp(16px, 5.2cqw, 56px); font-weight: 600; color: var(--fg);
  padding-bottom: 2cqh; border-bottom: 1px solid var(--rule); margin-bottom: .6cqh;
}
#root.t-editorial #bars { position: relative; gap: 4cqw; padding-top: 8cqh; border-bottom: 2px solid var(--fg); }
#root.t-editorial #bars::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0;
  background: repeating-linear-gradient(to top, var(--rule) 0 1.5px, transparent 1.5px 25%);
  pointer-events: none;
}
#root.t-editorial .equalsize { position: relative; z-index: 1; }
#root.t-editorial .bar { width: 56%; border-radius: .5cqw .5cqw 0 0; }
/* numeral sits INSIDE the bar top in a black-or-white colour that contrasts
   the bar (JS writes --val-contrast per bar); when the bar is too short to
   hold it the driver adds .val-above and it lifts above the bar, contrasting
   the chart background (--fg) instead */
#root.t-editorial .valbg {
  position: absolute; left: 0; right: 0; top: 1cqh; bottom: auto !important; transform: none;
  width: auto; height: auto; min-width: 0; min-height: 0;
  background: transparent; border: 0; box-shadow: none; white-space: nowrap;
}
#root.t-editorial .value { font-family: "Spectral", Georgia, serif; font-size: clamp(12px, calc(4.6cqw * 4 / var(--nopt, 4)), 46px); font-weight: 600; color: var(--val-contrast, var(--fg)); }
#root.t-editorial .val-above .valbg { top: auto; bottom: 100% !important; margin-bottom: .8cqh; }
#root.t-editorial .val-above .value { color: var(--fg); }
#root.t-editorial #labels { gap: 4cqw; margin-top: 1.8cqh; }
#root.t-editorial .barlabel { font-size: clamp(9px, 2cqw, 18px); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--fg-soft); }

/* =========================================================================
   06 · NEON ARCADE — value INSIDE the bar, glowing columns, self-dark stage
   (brings its own dark backdrop, so it pops on any slide background)
   ========================================================================= */
#root.t-neon { --fg: #eaf2ff; --fg-soft: #9fb4d6; }
#root.t-neon .wrapper { padding: 0; position: relative; background: radial-gradient(125% 105% at 50% 0%, #161d31 0%, #0a0d16 72%); }
#root.t-neon .wrapper::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .55;
  background:
    repeating-linear-gradient(to right, rgba(120, 160, 255, .07) 0 1px, transparent 1px 9%),
    repeating-linear-gradient(to top, rgba(120, 160, 255, .07) 0 1px, transparent 1px 12.5%);
}
#root.t-neon #header {
  font-family: "Oswald", sans-serif; text-transform: uppercase; letter-spacing: .12em;
  font-size: clamp(15px, 4.6cqw, 52px); font-weight: 600; color: #eaf2ff;
  padding: 4cqh 5cqw 0; text-shadow: 0 0 16px rgba(120, 170, 255, .4); position: relative;
}
#root.t-neon #bars { gap: 3.2cqw; padding: 6cqh 5cqw 0; align-items: flex-end; position: relative; }
#root.t-neon #bars::after {
  content: ""; position: absolute; left: 5cqw; right: 5cqw; bottom: 0; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(140, 180, 255, .7), transparent);
  box-shadow: 0 0 18px rgba(120, 170, 255, .6);
}
#root.t-neon .bar {
  width: 60%; min-height: 7cqh; border-radius: 3px 3px 0 0; border-bottom: 0;
  background: color-mix(in srgb, var(--bar-color, #39f) 26%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--bar-color, #39f) 70%, white 8%);
  box-shadow: 0 0 26px -2px color-mix(in srgb, var(--bar-color, #39f) 60%, transparent),
              inset 0 0 22px -6px color-mix(in srgb, var(--bar-color, #39f) 80%, transparent);
}
#root.t-neon .bar::after {
  content: ""; position: absolute; left: -1px; right: -1px; top: -3px; height: 4px; border-radius: 2px;
  background: var(--bar-color, #39f); box-shadow: 0 0 14px 1px var(--bar-color, #39f);
}
#root.t-neon .valbg {
  position: absolute; left: 0; right: 0; top: 1.4cqh; bottom: auto !important; transform: none;
  background: transparent; border: 0; box-shadow: none; display: block; text-align: center;
}
#root.t-neon .value {
  font-family: "Oswald", sans-serif; font-size: clamp(15px, 4.4cqw, 50px); font-weight: 700; color: #fff;
  text-shadow: 0 0 10px color-mix(in srgb, var(--bar-color, #39f) 85%, white),
               0 0 22px color-mix(in srgb, var(--bar-color, #39f) 70%, transparent);
}
#root.t-neon #labels { gap: 3.2cqw; padding: 1.6cqh 5cqw 3cqh; }
#root.t-neon .barlabel {
  font-family: "Oswald", sans-serif; font-size: clamp(9px, 1.9cqw, 17px); font-weight: 500;
  text-transform: uppercase; letter-spacing: .18em; color: #9fb4d6;
}

/* =========================================================================
   07 · BIG POP — labels jump to the TOP, value INSIDE the bar base, sticker shadow
   ========================================================================= */
#root.t-pop .wrapper { padding: 3.4cqh 4cqw 2.4cqh; }
#root.t-pop #header { order: 1; font-family: "Archivo Black", sans-serif; font-weight: 400; font-size: clamp(16px, 5.2cqw, 56px); color: var(--fg); letter-spacing: -.01em; text-align: center; }
#root.t-pop #labels { order: 2; gap: 2.4cqw; margin: 2cqh 0 0; flex-wrap: wrap; justify-content: center; }
#root.t-pop #labels .barlabel {
  flex: 0 0 auto; font-size: clamp(11px, 2.3cqw, 20px); font-weight: 800; color: var(--fg);
  background: var(--chip); border-radius: 999px; padding: 1cqh 2.2cqw; text-transform: uppercase; letter-spacing: .02em;
}
#root.t-pop #bars { order: 3; gap: 2cqw; padding-top: 5cqh; align-items: flex-end; }
#root.t-pop .bar {
  width: 88%; min-height: 18cqh; border-radius: 5cqw 5cqw 1.2cqw 1.2cqw;
  box-shadow: .8cqw .9cqh 0 0 rgba(20, 20, 30, .18);
}
#root.t-pop .bar::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 255, 255, .22), rgba(255, 255, 255, 0) 40%); pointer-events: none;
}
#root.t-pop .valbg {
  position: absolute; left: 0; right: 0; bottom: 1.4cqh !important; top: auto; transform: none;
  width: auto; min-width: 0; height: auto; min-height: 0;
  background: transparent; border: 0; box-shadow: none; text-align: center;
}
/* numeral contrasts the bar it sits on (JS writes --val-contrast per bar);
   too-short bar → .val-above lifts it above, contrasting the chart bg */
#root.t-pop .value { font-family: "Archivo Black", sans-serif; font-weight: 400; font-size: clamp(11px, calc(5.8cqw * 4 / var(--nopt, 4)), 60px); color: var(--val-contrast, #fff); text-shadow: 0 .25cqh 0 rgba(0, 0, 0, .2); }
#root.t-pop .val-above .valbg { bottom: 100% !important; margin-bottom: .5cqh; }
#root.t-pop .val-above .value { color: var(--fg); text-shadow: none; }

/* =========================================================================
   08 · STRIP / DOT PLOT — value as a dot's height, number floats above
   (inspired by a strip plot: clean markers read against a gridded axis)
   ========================================================================= */
#root.t-dot .wrapper { padding: 3.4cqh 4.6cqw 2.6cqh; }
#root.t-dot #header { font-size: clamp(16px, 5.2cqw, 56px); font-weight: 700; color: var(--fg); }
#root.t-dot #bars { position: relative; gap: 3cqw; padding-top: 8cqh; border-bottom: 2px solid var(--rule); }
#root.t-dot #bars::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(to top, var(--rule) 0 1px, transparent 1px 25%);
}
#root.t-dot .equalsize { position: relative; z-index: 1; }
#root.t-dot .bar { width: .8cqw; min-width: 3px; margin: 0 auto; border-radius: 999px; opacity: .9; }
#root.t-dot .valbg {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%); bottom: auto !important;
  width: 6.5cqw; height: 6.5cqw; min-width: 26px; min-height: 26px; border-radius: 50%;
  background: var(--bar-color, #39f); border: 0; display: block;
  box-shadow: 0 0 0 .5cqw color-mix(in srgb, var(--bar-color, #39f) 22%, transparent);
}
#root.t-dot .value {
  position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%); margin-bottom: 1.3cqh;
  font-size: clamp(12px, 2.8cqw, 28px); font-weight: 700; color: var(--fg); white-space: nowrap;
}
#root.t-dot #labels { gap: 3cqw; margin-top: 2cqh; }
#root.t-dot .barlabel { font-size: clamp(10px, 2.2cqw, 20px); font-weight: 600; color: var(--fg-soft); }

/* =========================================================================
   09 · BLOCKS — ONE TILE PER VOTE. scripts.js injects a .units stack
   (<div class="units"><div class="ucount"/><div class="ugrid"/></div>) into
   each .proportion and appends one .ublock per vote. Tiles fill bottom-up,
   left-to-right, five per row. The contract .bar is hidden in this theme.
   ========================================================================= */
#root.t-blocks .wrapper { padding: 3.4cqh 4cqw 2.6cqh; }
#root.t-blocks #header { font-size: clamp(16px, 5.2cqw, 56px); font-weight: 700; color: var(--fg); }
#root.t-blocks #bars { gap: 3.6cqw; padding-top: 7cqh; align-items: flex-end; border-bottom: 2px solid var(--rule); }
#root.t-blocks .bar { display: none; }
#root.t-blocks .units {
  display: flex; flex-direction: column; align-items: center;
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); width: 76%;
}
#root.t-blocks .ucount {
  font-size: clamp(14px, 3.6cqw, 36px); font-weight: 800; color: var(--fg);
  margin-bottom: .9cqh; font-variant-numeric: tabular-nums; line-height: 1.1;
}
#root.t-blocks .ugrid {
  display: flex; flex-wrap: wrap-reverse; justify-content: flex-start; align-content: flex-start;
  gap: .5cqw; width: 100%;
}
#root.t-blocks .ublock {
  width: calc((100% - 2cqw) / 5); aspect-ratio: 1 / 1; border-radius: 22%;
  background: var(--bar-color, #9a9aa4);
  box-shadow: inset 0 -.45cqh 0 rgba(0, 0, 0, .14), inset 0 .3cqh 0 rgba(255, 255, 255, .3);
  animation: ublock-in .32s cubic-bezier(.34, 1.45, .5, 1) backwards;
}
@keyframes ublock-in { from { transform: scale(.2); opacity: 0; } }
#root.t-blocks #labels { gap: 1.4cqw; margin-top: 2cqh; }
#root.t-blocks .barlabel { font-size: clamp(8px, 1.9cqw, 20px); font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--fg-soft); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 .3cqw; }
#root.t-blocks #bars { gap: 1.8cqw; }
#root.t-blocks .ugrid { gap: .4cqw; }

/* =========================================================================
   10 · FAN — capsule petals radiate from a bottom-centre hub across a polar
   grid; length = value, number rides upright just past each petal's tip.
   Legend chips (palette-dotted) sit between the header and the fan.
   ========================================================================= */
#root.t-fan .wrapper { padding: 3.4cqh 4cqw 2.4cqh; }
#root.t-fan #header { order: 1; font-size: clamp(15px, 4.8cqw, 52px); font-weight: 700; color: var(--fg); text-align: center; }
#root.t-fan #labels { order: 2; gap: 1.6cqw; margin: 1.8cqh 0 0; flex-wrap: wrap; justify-content: center; }
#root.t-fan #labels .barlabel {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .9cqw;
  font-size: clamp(10px, 1.9cqw, 17px); font-weight: 600; color: var(--fg-soft);
  background: var(--chip); padding: .8cqh 1.7cqw; border-radius: 999px; white-space: nowrap;
}
#root.t-fan #labels .barlabel::before {
  content: ""; flex: none; width: 1.6cqh; height: 1.6cqh; border-radius: 50%;
  background: var(--bar-color, #b6b6be);
}
#root.t-fan #bars {
  order: 3; position: relative; flex: 1 1 auto; min-height: 0; padding: 0; gap: 0;
  margin-top: 1cqh; border-bottom: 2px solid var(--rule); overflow: visible;
}
/* quartile ring grid: a true semicircle, rings every 14cqh */
#root.t-fan #bars::before {
  content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 112cqh; height: 56cqh; pointer-events: none;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0; overflow: hidden; opacity: .9;
  background: repeating-radial-gradient(circle at 50% 100%,
    transparent 0, transparent calc(14cqh - 1.5px), var(--rule) calc(14cqh - 1.5px), var(--rule) 14cqh);
}
/* hub */
#root.t-fan #bars::after {
  content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 5cqh; height: 2.5cqh; border-radius: 5cqh 5cqh 0 0; background: var(--fg); z-index: 4;
}
#root.t-fan #bars .equalsize { position: absolute; left: 50%; bottom: 0; width: 0; height: 100%; flex: none; z-index: 2; }
#root.t-fan #bars .proportion { position: absolute; left: 0; bottom: 0; width: 0; height: 56cqh; overflow: visible; }
/* petal length comes from --val (0–100, written by the driver alongside height)
   so it animates via the registered property — immune to %-height quirks */
#root.t-fan .bar {
  left: 0; bottom: 0; width: var(--pw, 7.5cqh); margin: 0 0 0 calc(var(--pw, 7.5cqh) / -2); min-height: var(--pw, 7.5cqh);
  height: calc(var(--val, 0) * var(--plf, .56cqh)) !important;
  transition: --val .5s cubic-bezier(.22, .61, .36, 1);
  border-radius: 999px; transform-origin: 50% 100%;
  box-shadow: 0 0 0 .55cqh color-mix(in srgb, var(--bar-color, #888) 16%, transparent);
}
/* angle + petal width come from per-item vars JS sets on each .equalsize,
   so the fan works for any option count (2–10), not just four */
#root.t-fan #bars .equalsize .bar { transform: rotate(var(--rot, 0deg)) translateY(-4cqh); }
#root.t-fan .valbg {
  position: absolute; left: 50%; top: 0; bottom: auto !important;
  width: auto; height: auto; min-width: 0; min-height: 0; transform: translate(-50%, -50%);
  background: transparent; border: 0; box-shadow: none; white-space: nowrap; z-index: 3;
}
#root.t-fan .value {
  display: block; font-size: clamp(12px, 3.4cqh, 34px); font-weight: 800; color: var(--fg);
  transform: translateY(-2.8cqh) rotate(var(--unrot, 0deg));
}

/* =========================================================================
   11 · RAINBOW — concentric arcs rise from the baseline; sweep angle = value
   (tallest bar = 90 ≙ 162°). The value badge rides the end of its arc.
   Needs --val (the same % the driver writes to height) on each .bar.
   ========================================================================= */
#root.t-rainbow .wrapper { padding: 3.4cqh 4cqw 2.4cqh; }
#root.t-rainbow #header { order: 1; font-size: clamp(15px, 4.8cqw, 52px); font-weight: 700; color: var(--fg); text-align: center; }
#root.t-rainbow #labels { order: 2; gap: 1.6cqw; margin: 1.8cqh 0 0; flex-wrap: wrap; justify-content: center; }
#root.t-rainbow #labels .barlabel {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .9cqw;
  font-size: clamp(10px, 1.9cqw, 17px); font-weight: 600; color: var(--fg-soft);
  background: var(--chip); padding: .8cqh 1.7cqw; border-radius: 999px; white-space: nowrap;
}
#root.t-rainbow #labels .barlabel::before {
  content: ""; flex: none; width: 1.6cqh; height: 1.6cqh; border-radius: 50%;
  background: var(--bar-color, #b6b6be);
}
#root.t-rainbow #bars {
  order: 3; position: relative; flex: 1 1 auto; min-height: 0; padding: 0; gap: 0;
  margin-top: 1cqh; border-bottom: 2px solid var(--rule); overflow: visible;
}
/* hub */
#root.t-rainbow #bars::after {
  content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 4.6cqh; height: 2.3cqh; border-radius: 5cqh 5cqh 0 0; background: var(--fg); z-index: 4;
}
#root.t-rainbow #bars .equalsize { position: absolute; inset: 0; height: 100%; flex: none; }
/* ring radius/thickness set per item by JS (--R/--Rmid/--band) so any N works */
#root.t-rainbow .bar {
  left: 50%; right: auto; bottom: calc(var(--R) * -1); margin: 0 0 0 calc(var(--R) * -1);
  width: calc(var(--R) * 2); height: calc(var(--R) * 2) !important;
  border-radius: 50%;
  background-color: transparent !important; background-image: none;
  box-shadow: none; transition: --val .55s cubic-bezier(.22, .61, .36, 1);
}
/* faint 180° track */
#root.t-rainbow .bar::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: conic-gradient(from 270deg, var(--track) 0 180deg, transparent 0);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
  mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
}
/* the live arc */
#root.t-rainbow .bar::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 1;
  background: conic-gradient(from 270deg, var(--bar-color, #9a9aa4) 0 calc(var(--val, 0) * 1.8deg), transparent 0);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
  mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
}
/* arm pinned at the origin; rotates with the arc end */
#root.t-rainbow .valbg {
  position: absolute; left: 50%; top: 50%; bottom: auto !important;
  width: var(--Rmid); height: 0; min-width: 0; min-height: 0; margin: 0;
  background: transparent; border: 0; box-shadow: none; border-radius: 0; display: block;
  transform-origin: 0 50%; transform: rotate(calc(180deg + var(--val, 0) * 1.8deg)); z-index: 2;
}
#root.t-rainbow .value {
  position: absolute; right: 0; top: 0;
  width: 7.2cqh; height: 7.2cqh; min-width: 26px; min-height: 26px;
  transform: translate(50%, -50%) rotate(calc(-180deg - var(--val, 0) * 1.8deg));
  border-radius: 50%; background: #fff; border: .55cqh solid var(--bar-color, #9a9aa4);
  box-shadow: 0 .6cqh 1.8cqh rgba(20, 20, 35, .28);
  display: flex; align-items: center; justify-content: center;
  font-size: clamp(10px, 2.7cqh, 26px); font-weight: 800; color: #16161c;
}

/* =========================================================================
   12 · RAINBOW SOLID — same as Rainbow but with zero gaps: a true rainbow.
   Each band touches the next, from innermost (4th option) to outermost (1st).
   ========================================================================= */
#root.t-rainbow-solid .wrapper { padding: 3.4cqh 4cqw 2.4cqh; }
#root.t-rainbow-solid #header { order: 1; font-size: clamp(15px, 4.8cqw, 52px); font-weight: 700; color: var(--fg); text-align: center; }
#root.t-rainbow-solid #labels { order: 2; gap: 1.6cqw; margin: 1.8cqh 0 0; flex-wrap: wrap; justify-content: center; }
#root.t-rainbow-solid #labels .barlabel {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .9cqw;
  font-size: clamp(10px, 1.9cqw, 17px); font-weight: 600; color: var(--fg-soft);
  background: var(--chip); padding: .8cqh 1.7cqw; border-radius: 999px; white-space: nowrap;
}
#root.t-rainbow-solid #labels .barlabel::before {
  content: ""; flex: none; width: 1.6cqh; height: 1.6cqh; border-radius: 50%;
  background: var(--bar-color, #b6b6be);
}
#root.t-rainbow-solid #bars {
  order: 3; position: relative; flex: 1 1 auto; min-height: 0; padding: 0; gap: 0;
  margin-top: 1cqh; border-bottom: 2px solid var(--rule); overflow: visible;
}
/* hub */
#root.t-rainbow-solid #bars::after {
  content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 4.6cqh; height: 2.3cqh; border-radius: 5cqh 5cqh 0 0; background: var(--fg); z-index: 4;
}
#root.t-rainbow-solid #bars .equalsize { position: absolute; inset: 0; height: 100%; flex: none; }
/* ring radius/thickness set per item by JS (--R/--Rmid/--band) so any N works */
#root.t-rainbow-solid .bar {
  left: 50%; right: auto; bottom: calc(var(--R) * -1); margin: 0 0 0 calc(var(--R) * -1);
  width: calc(var(--R) * 2); height: calc(var(--R) * 2) !important;
  border-radius: 50%;
  background-color: transparent !important; background-image: none;
  box-shadow: none; transition: --val .55s cubic-bezier(.22, .61, .36, 1);
}
/* no track (solid rainbow) */
#root.t-rainbow-solid .bar::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: transparent;
}
/* the live arc */
#root.t-rainbow-solid .bar::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 1;
  background: conic-gradient(from 270deg, var(--bar-color, #9a9aa4) 0 calc(var(--val, 0) * 1.8deg), transparent 0);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
  mask: radial-gradient(closest-side, transparent calc(100% - var(--band)), #000 calc(100% - var(--band) + 1px), #000 calc(100% - 1px), transparent 100%);
}
/* arm pinned at the origin; rotates with the arc end */
#root.t-rainbow-solid .valbg {
  position: absolute; left: 50%; top: 50%; bottom: auto !important;
  width: var(--Rmid); height: 0; min-width: 0; min-height: 0; margin: 0;
  background: transparent; border: 0; box-shadow: none; border-radius: 0; display: block;
  transform-origin: 0 50%; transform: rotate(calc(180deg + var(--val, 0) * 1.8deg)); z-index: 2;
}
#root.t-rainbow-solid .value {
  position: absolute; right: 0; top: 0;
  width: 9cqh; height: 9cqh; min-width: 30px; min-height: 30px;
  transform: translate(50%, -50%) rotate(calc(-180deg - var(--val, 0) * 1.8deg));
  border-radius: 50%; background: #fff; border: .6cqh solid var(--bar-color, #9a9aa4);
  box-shadow: 0 .6cqh 1.8cqh rgba(20, 20, 35, .28);
  display: flex; align-items: center; justify-content: center;
  font-size: clamp(11px, 3.2cqh, 30px); font-weight: 800; color: #16161c;
}
/* Rainbow winner highlight: the legend pills run in reading order, not next
   to their arcs, so the audience can't map arc→option. The driver marks the
   current leader(s) with .is-leader (ties all get it); the winning pill lifts
   to a white card ringed and starred in the option's colour. The transparent
   border on every pill reserves the ring's space so nothing shifts. */
#root.t-rainbow #labels .barlabel,
#root.t-rainbow-solid #labels .barlabel {
  border: .3cqh solid transparent;
  transition: background .3s ease, border-color .3s ease, color .3s ease;
}
#root.t-rainbow #labels .barlabel.is-leader,
#root.t-rainbow-solid #labels .barlabel.is-leader {
  background: #fff; color: #16161c; font-weight: 800;
  border-color: var(--bar-color, #b6b6be);
  box-shadow: 0 .5cqh 1.6cqh rgba(20, 20, 35, .22);
}
#root.t-rainbow #labels .barlabel.is-leader::after,
#root.t-rainbow-solid #labels .barlabel.is-leader::after {
  content: "★"; color: var(--bar-color, #b6b6be); font-size: .9em; line-height: 1;
}

/* at 6+ options the rings get thin; size each badge to its ring thickness
   (Router 74 − Rinner 15 = 59, split across --nopt rings) so that even when
   every option is tied — all badges on the same radial ray — they nest within
   their bands instead of piling up. */
#root.many-opts.t-rainbow-solid .value {
  width: clamp(20px, calc(1cqh * 56 / var(--nopt, 6)), 40px);
  height: clamp(20px, calc(1cqh * 56 / var(--nopt, 6)), 40px);
  min-width: 0; min-height: 0;
  border-width: .4cqh; font-size: clamp(8px, calc(1cqh * 19 / var(--nopt, 6)), 22px);
}

/* =========================================================================
   14 · BAUHAUS — concentric filled circles, radius ∝ value, largest behind
   (an inline z-index keeps smaller circles on top). The value rides the top
   edge of each circle in a white pill; palette-dotted legend sits below.
   The host sets --r (radius, cqh) and z-index per .bar in render().
   ========================================================================= */
#root.t-bauhaus .wrapper { padding: 3.6cqh 4cqw 3cqh; }
#root.t-bauhaus #header { font-size: clamp(15px, 4.8cqw, 50px); font-weight: 800; color: var(--fg); text-align: center; letter-spacing: -.01em; }
#root.t-bauhaus #bars { position: relative; flex: 1 1 auto; min-height: 0; padding: 0; gap: 0; margin-top: 1.6cqh; }
#root.t-bauhaus #bars .equalsize { position: absolute; inset: 0; height: 100%; flex: none; }
#root.t-bauhaus .proportion { position: absolute; inset: 0; width: auto; height: 100%; }
#root.t-bauhaus .bar {
  position: absolute; left: 50%; top: 50%; right: auto; bottom: auto; margin: 0;
  width: calc(var(--r, 20cqh) * 2); height: calc(var(--r, 20cqh) * 2) !important;
  transform: translate(-50%, -50%); border-radius: 50%;
  background-color: var(--bar-color, #888888); background-image: none;
  transition: width .5s cubic-bezier(.22, .61, .36, 1), height .5s cubic-bezier(.22, .61, .36, 1);
}
#root.t-bauhaus .valbg { display: none; }
#root.t-bauhaus #labels { gap: 1.8cqw 2.4cqw; margin-top: 2.4cqh; flex-wrap: wrap; justify-content: center; }
#root.t-bauhaus #labels .barlabel {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 1cqw;
  font-size: clamp(10px, 1.9cqw, 17px); font-weight: 600; color: var(--fg); white-space: nowrap;
}
#root.t-bauhaus #labels .barlabel b { font-weight: 800; }
#root.t-bauhaus #labels .barlabel::before {
  content: ""; flex: none; width: 2.2cqh; height: 2.2cqh; border-radius: 50%; background: var(--bar-color, #b6b6be);
}

/* =========================================================================
   13 · HORIZONTAL BARS — rows, not columns. Each option gets a full-width
   row [ label | track+bar | value ], so long answer text never truncates and
   the chart reads top-to-bottom like a leaderboard. Width = value (--val);
   the driver's inline height is overridden. A per-row .rowlabel is injected
   into each .equalsize (hidden by every other theme).
   ========================================================================= */
#root.t-hbars .wrapper { padding: 4.4cqh 5cqw; }
#root.t-hbars #header { font-size: clamp(16px, 4.8cqw, 50px); font-weight: 700; color: var(--fg); text-align: left; margin-bottom: 3.4cqh; }
#root.t-hbars #bars {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 2.4cqw; row-gap: 2.6cqh; align-content: center; padding: 0 9cqw 0 0;
}
/* rows dissolve into the grid so the label column = widest label (no wasted
   fixed-width strip on the left), and every bar starts at the same x */
#root.t-hbars #bars .equalsize { display: contents; }
#root.t-hbars .rowlabel {
  display: block; align-self: center; text-align: right;
  font-size: clamp(11px, 2.4cqw, 24px); font-weight: 600; color: var(--fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.15; max-width: 34cqw;
}
#root.t-hbars .proportion {
  align-self: center; position: relative; width: auto;
  height: clamp(18px, 6cqh, 52px); background: var(--track); border-radius: 999px; overflow: visible;
}
#root.t-hbars .bar {
  position: absolute; left: 0; top: 0; bottom: 0; right: auto; margin: 0;
  height: auto !important; width: calc(var(--val, 0) * 1%); min-width: 4cqh;
  border-radius: 999px; transition: --val .55s cubic-bezier(.22, .61, .36, 1);
  box-shadow: inset 0 -.5cqh 0 rgba(0, 0, 0, .12);
}
#root.t-hbars .valbg {
  position: absolute; left: 100%; top: 50%; bottom: auto !important;
  transform: translate(2.4cqw, -50%); background: transparent; border: 0; box-shadow: none;
  white-space: nowrap; min-width: 0; min-height: 0;
}
#root.t-hbars .value { font-size: clamp(13px, 3.4cqh, 30px); font-weight: 800; color: var(--fg); }
#root.t-hbars #labels { display: none; }

/* =========================================================================
   ENHANCEMENTS (opt-in via classes / injected els) — shared across themes.
   These lie dormant until their class is applied (Phase 2 wires the toggles).
   ========================================================================= */
/* per-row label: hidden everywhere except Horizontal Bars */
#root .rowlabel { display: none; }

/* secondary count line for the "Percent + count" number mode (Blocks shows
   its number via .ucount, so cover that too) */
#root .value .cnt, #root .ucount .cnt {
  display: block; font-size: .46em; font-weight: 600; opacity: .62;
  line-height: 1; margin-top: .18em; letter-spacing: 0;
}
/* themes whose value badge is too small/rotated for a second line: percent only */
#root.t-fan .value .cnt,
#root.t-rainbow-solid .value .cnt { display: none; }
#root.t-hbars .value .cnt { display: inline; font-size: .62em; margin: 0 0 0 .5em; }

/* hide the question title so the chart/key fills the freed space.
   #bars is flex:1, so it (and the cqh-based Fan/Rainbow geometry) expand to fill. */
#root.no-title #header { display: none; }

/* winner highlight: fade the also-rans so the leader pops */
#root.hl-winner #bars .equalsize { transition: opacity .45s ease; }
#root.hl-winner #bars .equalsize:not(.is-leader) { opacity: .4; }
#root.hl-winner #bars .equalsize.is-leader .rowlabel { font-weight: 800; }
/* hbars rows are display:contents (grid), so opacity must hit the children */
#root.hl-winner.t-hbars #bars .equalsize:not(.is-leader) .rowlabel,
#root.hl-winner.t-hbars #bars .equalsize:not(.is-leader) .proportion { opacity: .4; transition: opacity .45s ease; }

/* vote tick: brief pulse on the number that just changed */
@keyframes vote-tick {
  0% { transform: scale(1); }
  35% { transform: scale(1.32); }
  100% { transform: scale(1); }
}
#root .value.bumped, #root .ucount.bumped { animation: vote-tick .5s cubic-bezier(.34, 1.5, .5, 1); }
/* fan/rainbow value carry a rotation in their transform — pulse a child wrap instead */
#root.t-fan .value.bumped, #root.t-rainbow-solid .value.bumped { animation: none; }
#root.t-fan .value.bumped, #root.t-rainbow-solid .value.bumped { filter: brightness(1.18); transition: filter .12s; }

/* reserve the top-right corner for the total/leader chip so centered titles
   and the Fan/Rainbow legend don't slide underneath it */
#root.has-chip.t-flat #header,
#root.has-chip.t-pop #header,
#root.has-chip.t-blocks #header,
#root.has-chip.t-fan #header,
#root.has-chip.t-rainbow-solid #header { padding-left: 22cqw; padding-right: 22cqw; }
/* editorial header is left-aligned — only clear the chip on the right so the
   title keeps its full width and doesn't wrap into wasted vertical space */
#root.has-chip.t-editorial #header { padding-right: 18cqw; }
#root.has-chip.t-fan #labels,
#root.has-chip.t-rainbow-solid #labels { padding-left: 14cqw; padding-right: 14cqw; }
#root.has-chip.t-hbars #header { padding-right: 18cqw; }

/* compact the Fan/Rainbow legend ("key") when there are many options, so its
   extra wrapped rows don't eat the vertical room the arcs/petals need */
#root.many-opts.t-fan #labels,
#root.many-opts.t-rainbow-solid #labels { gap: .8cqw 1.1cqw; margin-top: 1.2cqh; }
#root.many-opts.t-fan #labels .barlabel,
#root.many-opts.t-rainbow-solid #labels .barlabel { font-size: clamp(9px, 1.75cqw, 16px); padding: .6cqh 1.5cqw; gap: .7cqw; }
#root.many-opts.t-fan #labels .barlabel::before,
#root.many-opts.t-rainbow-solid #labels .barlabel::before { width: 1.3cqh; height: 1.3cqh; }

/* column themes at 6+ options: let the under-bar key wrap to its full text
   (no ellipsis) and dial the value figures down so nothing is clipped */
#root.many-opts.t-flat .barlabel,
#root.many-opts.t-editorial .barlabel {
  white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.12;
  font-size: clamp(8px, 1.7cqw, 15px); letter-spacing: .02em;
}
#root.many-opts.t-flat .barlabel { padding: .7cqh .6cqw; }
#root.many-opts.t-editorial .barlabel { font-size: clamp(7px, 1.35cqw, 13px); letter-spacing: 0; }
#root.many-opts.t-editorial #bars,
#root.many-opts.t-editorial #labels { gap: 2cqw; }
#root.many-opts.t-pop .barlabel { white-space: normal; font-size: clamp(8px, 1.5cqw, 14px); padding: .7cqh 1.2cqw; line-height: 1.1; }
#root.many-opts.t-flat .value { font-size: clamp(11px, calc(6.2cqw * 3.3 / var(--nopt, 4)), 40px); }
#root.many-opts.t-editorial .value { font-size: clamp(10px, calc(4.6cqw * 3.3 / var(--nopt, 4)), 34px); }
#root.many-opts.t-pop .value { font-size: clamp(10px, calc(4.4cqw * 4 / var(--nopt, 4)), 36px); }

/* centered headlines (Flat/Pop/Blocks) at many options: shrink the title and
   tighten the chip gutter so it sits on one line instead of wrapping */
#root.many-opts.t-flat #header,
#root.many-opts.t-pop #header,
#root.many-opts.t-blocks #header { font-size: clamp(14px, 3.6cqw, 34px); line-height: 1.12; text-wrap: balance; }
#root.has-chip.many-opts.t-flat #header,
#root.has-chip.many-opts.t-pop #header,
#root.has-chip.many-opts.t-blocks #header { padding-left: 17cqw; padding-right: 17cqw; }
/* Big Pop sets the title in Archivo Black (much wider) — shrink it a touch more */
#root.many-opts.t-pop #header { font-size: clamp(12px, 3cqw, 28px); }
/* Pop's labels are a wrapped sticker cloud (not column-bound); keep the row's
   top-right corner clear of the votes chip */
#root.has-chip.t-pop #labels { padding-right: 15cqw; }

/* ---------------------------------------------------------------------------
   Live-preview (?demo=1) static render. The preview re-renders on every edit,
   so the bar grow-from-bottom transition, the wrapper fade-up, per-theme --val
   height tweens and value count-ups all replay each keystroke — reads as a
   jarring morph. Suppress every transition/animation under #root in preview
   mode so edits apply instantly. No transitionend/animationend handlers depend
   on these, and the present-mode chart (no .preview-static) is unaffected. */
#root.preview-static,
#root.preview-static * {
  transition: none !important;
  animation: none !important;
}

/* ---------------------------------------------------------------------------
   Slide timer (interaction type "timer"). A clock, not a chart: no bars, no
   labels, no cover. It lives inside #root so it inherits the theme font and the
   --fg/--fg-soft variables, and so #root's container-type: size makes the
   digits scale with the slide box rather than the viewport — the chart's
   countdown pill is document.body-fixed at 18px and does not do this.

   The readout is deliberately the loudest thing on the slide: a booth or a
   breakout has to read it across a room. */
#root.timer-mode { display: flex; align-items: center; justify-content: center; }

#root #timer-face {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2cqh;
  width: 100%;
  padding: 4cqh 4cqw;
  box-sizing: border-box;
  text-align: center;
}

#root #timer-title {
  font-size: clamp(12px, 4cqw, 44px);
  font-weight: 600;
  color: var(--fg-soft);
  letter-spacing: .01em;
  max-width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#root #timer-readout {
  /* tabular-nums stops the clock jittering horizontally as digits change —
     same reasoning as #root .value. */
  font-variant-numeric: tabular-nums;
  font-size: clamp(48px, 34cqw, 460px);
  font-weight: 800;
  line-height: .9;
  color: var(--fg);
  letter-spacing: -.02em;
}

/* Under 10s: the clock itself carries the warning, so no extra chrome is
   needed. Colour only — never a flash or a pulse, which on a projector at the
   front of a room reads as a rendering fault. */
#root #timer-face.is-urgent #timer-readout { color: #d92d20; }

/* Expired. The readout holds at 0:00 and the caption does the talking, because
   the presenter's next action is to reset, not to read a number. */
#root #timer-face.is-expired #timer-readout { color: var(--fg-soft); opacity: .45; }
#root #timer-face.is-expired #timer-label {
  font-size: clamp(20px, 9cqw, 110px);
  font-weight: 800;
  letter-spacing: .04em;
  color: #d92d20;
}

/* Paused reads as deliberately held, not broken. */
#root #timer-face.is-paused #timer-readout { opacity: .5; }

#root #timer-label {
  font-size: clamp(11px, 2.6cqw, 26px);
  font-weight: 500;
  color: var(--fg-soft);
  letter-spacing: .06em;
  text-transform: uppercase;
  min-height: 1em;
}
