*{box-sizing:border-box}

/* Family tokens, light values, ported from the family's first tool. Dark values live in
   theme.css; every token with a dark value is marked themed in the family's token list.
   --primary-* follow the project's accent (--tool-accent, from the project's own tokens)
   and need no dark value: they recompute from the dark --tool-accent and --surface. */
:root{
 color-scheme:light;
 --primary-fg:var(--tool-accent);
 --primary-bg:color-mix(in srgb,var(--tool-accent) 12%,var(--surface));
 --primary-soft-border:color-mix(in srgb,var(--tool-accent) 40%,var(--surface));
 /* State colours: green means go, red means stop, amber waits, blue informs. */
 --ok-bg:#e7f4ec;--ok-fg:#1f6b39;--ok-border:#acd8b9;
 --danger:#a02020;--danger-bg:#fee;--danger-border:#fbb;
 --danger-solid:#c0392b;--danger-solid-border:#a5281b;
 --warn-bg:#fff4e5;--warn-border:#f0b968;--warn-fg:#8a5200;
 --info-bg:#e6eefb;--info-border:#b7c9ea;--info-fg:#274b8f;
 /* Debug orange marks an audience, not a severity: UI that exists only in debug mode. */
 --debug-bg:#fff1e2;--debug-fg:#8f4400;--debug-border:#d47f2a;--debug-hover:#ffe3c9;
 /* The page is the canvas; --surface is a panel painted on it. Keep them two tokens. */
 --page-bg:#fff;
 --surface:#fff;--surface-raised:#fafafa;--surface-btn:#f2f2f2;
 --surface-hover:#e6e6e6;--surface-hover-soft:#f0f0f0;--surface-modal:#fff;--surface-press:#dcdcdc;
 --border:#ddd;--border-subtle:#eee;--border-strong:#888;--border-modal:#ccc;
 --text:#222;--text-muted:#707070;--text-faint:#999;
 --focus:#3c2da0;--focus-ring:#5b4bc4;
 --link:#3c5da0;--link-hover:#2c4680;
 --code-bg:transparent;--code-fg:#555;
 --th-bg:#fafafa;--th-fg:#555;
 /* Theme-invariant: no dark value. */
 --on-solid:#fff;
 --shadow-pop:0 6px 24px rgba(0,0,0,.18);
 --shadow-modal:0 12px 40px rgba(0,0,0,.25);
 --backdrop:rgba(0,0,0,.45);
 --ctl-h:calc(1.575rem + 2px);--ctl-h-sm:calc(1.216rem + 2px);
 --r-xs:3px;--r-sm:5px;--r-md:6px;--r-lg:8px;
}

/* Family tokens, dark values. Dark is the primary theme: design and check it first.
   Only tokens go here; a component never carries its own html.dark-mode colour rule. */
html.dark-mode{
 color-scheme:dark;
 --ok-bg:#1e3325;--ok-fg:#6bd189;--ok-border:#2f5a3a;
 --danger:#ff8080;--danger-bg:#3a2020;--danger-border:#5a2020;
 --danger-solid:#c0392b;--danger-solid-border:#a5281b;
 --warn-bg:#3a2d05;--warn-border:#7a5a1a;--warn-fg:#ffd08a;
 --info-bg:#182742;--info-border:#2f4a7a;--info-fg:#8fb2ee;
 --debug-bg:#3d2208;--debug-fg:#ffa14a;--debug-border:#9a5c1a;--debug-hover:#4e2d0b;
 --page-bg:#1a1a1a;
 --surface:#1e1e1e;--surface-raised:#1a1d22;--surface-btn:#2a2a2a;
 --surface-hover:#333;--surface-hover-soft:#2a2a2a;--surface-modal:#1a1a1a;--surface-press:#3d3d3d;
 --border:#444;--border-subtle:#333;--border-strong:#767676;--border-modal:#444;
 --text:#ddd;--text-muted:#aaa;--text-faint:#777;
 --focus:#8a7bff;--focus-ring:#9d90ff;
 --link:#79b8ff;--link-hover:#a8d0ff;
 --code-bg:#2a2a2a;--code-fg:#ddd;
 --th-bg:#222;--th-fg:#aaa;
}

/* Text-level rules that belong to no one component. */
h1,h2,h3{line-height:1.25;color:var(--text)}
h1{font-size:1.6em;margin:.8em 0 .3em}
h2{font-size:1.2em;margin:1.4em 0 .4em}
a{color:var(--link)}
a:hover{color:var(--link-hover)}
a:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;border-radius:var(--r-xs)}
/* Light has no code background, so its padding is invisible; the box appears only in dark. */
code{font-family:ui-monospace,monospace;font-size:.88em;
     background:var(--code-bg);color:var(--code-fg);
     padding:0 .2em;border-radius:var(--r-xs)}
.mono{font-family:ui-monospace,monospace}

/* The page: html carries the background so the whole viewport is one colour in both themes. */
html{background:var(--page-bg)}
body{margin:0;font-family:system-ui,sans-serif;color:var(--text);background:var(--page-bg);line-height:1.5}
.fam-page{max-width:1400px;margin:0 auto 1.5em;padding:0 1.5em}
.muted{color:var(--text-muted)}
.nowrap{white-space:nowrap}
/* The /style page's layout helpers. */
.fam-ref-row{display:flex;flex-wrap:wrap;gap:.5em;align-items:center;margin:.5em 0 1em}
.fam-ref .notice{margin:.5em 0}

/* The family header bar: full width, its content aligned to the page column. */
.fam-header{position:sticky;top:0;z-index:20;background:var(--surface);border-bottom:1px solid var(--border-subtle)}
.fam-header-inner{max-width:1400px;margin:0 auto;padding:.55em 1.5em;display:flex;align-items:center;gap:.7em}
.fam-brand{display:inline-flex;align-items:center;gap:.55em;color:var(--text);text-decoration:none;
           font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:.95em}
.fam-brand:hover{color:var(--text);text-decoration:none}
.fam-mark{width:22px;height:22px;flex:none;color:var(--primary-fg)}
/* The mark's colours come from tokens, which beat the SVG's own fill attributes. */
.fam-mark rect{fill:var(--primary-fg)}
.fam-mark text{fill:var(--surface)}
.fam-header-actions{margin-left:auto;display:flex;align-items:center;gap:.4em}
/* The toggle shows the theme it switches TO: a sun in dark, a moon in light. */
html.dark-mode .fam-theme-toggle .th-moon{display:none}
html:not(.dark-mode) .fam-theme-toggle .th-sun{display:none}

.fam-footer{max-width:1400px;margin:3em auto 0;padding:1em 1.5em;text-align:center;font-size:.82em;
            color:var(--text-muted);border-top:1px solid var(--border-subtle)}
/* Inline Lucide icons: 1em, currentColor, baseline-aligned. */
.ic{width:1em;height:1em;display:inline-block;vertical-align:-.125em;flex:none}
.btn-ic{margin-right:.35em}
.btn-ic-r{margin-left:.28em;opacity:.8}

/* Family buttons. One base owns geometry; modifiers change only colour, shape or size. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.45em;
  box-sizing:border-box;
  padding:.4em .8em;font-family:system-ui,sans-serif;font-size:.875rem;line-height:1;
  color:var(--text);background:var(--surface-btn);border:1px solid var(--border);
  border-radius:var(--r-sm);cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:background .15s,border-color .15s,color .15s}
.btn:hover{background:var(--surface-hover);border-color:var(--border-strong);text-decoration:none}
/* Declared after :hover so a pressed button reads as pressed while the pointer is over it. */
.btn:active{background:var(--surface-press)}
/* The family focus ring: solid, 2px outside the control, so it touches only what the control sits on. */
.btn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.btn .ic{width:1.05em;height:1.05em;flex:none}
.btn img{width:1.05em;height:1.05em;object-fit:contain;display:block}
.btn.confirm{background:var(--primary-bg);color:var(--primary-fg);border-color:var(--primary-soft-border)}
.btn.confirm:hover{background:var(--primary-bg);border-color:var(--primary-fg)}
.btn.danger{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-border)}
.btn.danger:hover{background:var(--danger-bg);border-color:var(--danger)}
.btn.confirm.soft{background:transparent;border-color:var(--primary-soft-border);color:var(--primary-fg)}
.btn.confirm.soft:hover{background:var(--primary-bg);border-color:var(--primary-fg)}
.btn.danger.soft{background:transparent;border-color:var(--danger-border);color:var(--danger)}
.btn.danger.soft:hover{background:var(--danger-bg);border-color:var(--danger)}
.btn.ghost{background:none;border-color:transparent;color:var(--text-muted)}
.btn.ghost:hover{background:var(--surface-hover);border-color:transparent;color:var(--text)}
/* Must follow .btn.ghost:hover, which ties with it on specificity. Confirm and danger get no
   press fill: their hover is border-only so the tint survives. */
.btn.ghost:active{background:var(--surface-press);color:var(--text)}
.btn.icon{padding:.4em;width:2.1em;height:2.1em;gap:0}
.btn.icon .ic{width:1.15em;height:1.15em}
.btn.sm{padding:.26em .55em;font-size:.8rem}
.btn.sm.icon{padding:.26em;width:1.7em;height:1.7em}
.btn.disabled,.btn:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}
.btn[hidden]{display:none}
.btn[aria-pressed="true"]{background:var(--surface-hover);border-color:var(--border-strong)}
/* Debug marks an audience: a control that exists only while debug mode is on. The
   aria-pressed rule settles the tie with the grey pressed state above. */
.btn.debug{background:var(--debug-bg);color:var(--debug-fg);border-color:var(--debug-border)}
.btn.debug:hover{background:var(--debug-hover);border-color:var(--debug-fg)}
.btn.debug[aria-pressed="true"]{background:var(--debug-hover);border-color:var(--debug-fg)}

/* Form controls. Tokenised, so dark comes from the token swap; never add a per-control dark rule. */
/* A .field and a .btn of the same size class are the same height (var(--ctl-h)). */
.field{font-family:inherit;font-size:.875rem;height:var(--ctl-h);padding:0 .6em;
       border:1px solid var(--border-strong);border-radius:var(--r-sm);background:var(--surface);
       color:var(--text);line-height:normal;max-width:100%}
.field:focus{border-color:var(--focus);outline:2px solid var(--focus-ring);outline-offset:2px}
.field.mono{font-family:ui-monospace,monospace;font-size:.82rem;letter-spacing:.3px}
.field.sm{height:var(--ctl-h-sm);font-size:.8rem;padding:0 .5em}
/* A select wears the .field box. The native arrow is kept: it follows the element's colour. */
select.field{padding-right:1.5em;cursor:pointer}
select.field.sm{padding-right:1.3em}
.field-row{display:flex;gap:.5em;align-items:center;flex-wrap:wrap}
.field-row>label{color:var(--text);font-size:.9em}
/* A label is content, not chrome: var(--text), as strong as the value it names. */
.field-label{display:flex;flex-direction:column;gap:.3em;font-size:.85em;color:var(--text)}
.field-label.inline{flex-direction:row;align-items:center;gap:.5em}
/* Vendor track and thumb pseudo-elements cannot share one selector list. */
.range{appearance:none;-webkit-appearance:none;width:100%;max-width:12em;
       height:var(--ctl-h);background:transparent;cursor:pointer}
.range::-webkit-slider-runnable-track{height:.35em;border-radius:var(--r-xs);
  background:var(--surface-btn);border:1px solid var(--border-strong)}
.range::-moz-range-track{height:.35em;border-radius:var(--r-xs);
  background:var(--surface-btn);border:1px solid var(--border-strong)}
.range::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;
  width:1em;height:1em;margin-top:-.36em;border-radius:50%;
  background:var(--primary-fg);border:1px solid var(--primary-fg)}
.range::-moz-range-thumb{width:1em;height:1em;border-radius:50%;
  background:var(--primary-fg);border:1px solid var(--primary-fg)}
.range:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.range:disabled{opacity:.5;cursor:not-allowed}
/* Checkbox: the accent fill means on. The tick paints in var(--surface), which contrasts in both themes. */
.check{appearance:none;-webkit-appearance:none;margin:0;flex:none;
       width:1.05em;height:1.05em;display:inline-grid;place-content:center;cursor:pointer;
       border:1px solid var(--border-strong);border-radius:var(--r-xs);background:var(--surface);
       transition:background .15s,border-color .15s}
.check:hover{border-color:var(--text-muted)}
.check:checked,.check:indeterminate{background:var(--primary-fg);border-color:var(--primary-fg)}
.check::after{content:"";width:.3em;height:.6em;border:solid var(--surface);
              border-width:0 2px 2px 0;transform:rotate(45deg) scale(0);
              transition:transform .12s ease-out;margin-top:-.1em}
.check:checked::after{transform:rotate(45deg) scale(1)}
.check:indeterminate::after{width:.58em;height:0;margin:0;
                            border-width:0 0 2px 0;transform:none}
.check:focus-visible{border-color:var(--focus);outline:2px solid var(--focus-ring);outline-offset:2px}
.check:disabled{opacity:.5;cursor:not-allowed}
.check-row{display:inline-flex;align-items:center;gap:.45em;cursor:pointer;
           font-size:.9em;color:var(--text)}

/* The shared table skin: every th supplies its own tokenised colours. */
table{width:100%;border-collapse:collapse;margin:1em 0;font-size:.92em;table-layout:auto}
th,td{padding:.5em .55em;text-align:left;border-bottom:1px solid var(--border-subtle);vertical-align:middle}
th{background:var(--th-bg);color:var(--th-fg);font-size:.78em;text-transform:uppercase;
   letter-spacing:.04em;white-space:nowrap}
td{color:var(--text)}

/* A chip is a short status label. Its colour says the state; its words say it too. */
.chip{display:inline-flex;align-items:center;gap:.35em;padding:.12em .55em;border:1px solid var(--border);
      border-radius:999px;font-size:.8em;line-height:1.5;white-space:nowrap;
      color:var(--text-muted);background:var(--surface-raised)}
.chip .ic{width:1.05em;height:1.05em}
.chip.primary{background:var(--primary-bg);border-color:var(--primary-soft-border);color:var(--primary-fg)}
.chip.ok{background:var(--ok-bg);border-color:var(--ok-border);color:var(--ok-fg)}
.chip.warn{background:var(--warn-bg);border-color:var(--warn-border);color:var(--warn-fg)}
.chip.danger{background:var(--danger-bg);border-color:var(--danger-border);color:var(--danger)}
.chip.info{background:var(--info-bg);border-color:var(--info-border);color:var(--info-fg)}
.chip.debug{background:var(--debug-bg);border-color:var(--debug-border);color:var(--debug-fg)}

/* One alert primitive. The hook class on the markup stays; only the look comes from .notice. */
.notice{display:flex;align-items:center;gap:.55em;padding:.6em .8em;
        border:1px solid;border-radius:var(--r-md);font-size:.9em;line-height:1.4}
.notice[hidden]{display:none}
.notice .ic{flex:none;width:1.15em;height:1.15em}
.notice .meta{margin-left:auto;font-weight:400;font-size:.88em;opacity:.9}
.notice.top{align-items:flex-start}
.notice.top .ic{margin-top:.1em}
.notice.info{background:var(--info-bg);border-color:var(--info-border);color:var(--info-fg)}
.notice.ok{background:var(--ok-bg);border-color:var(--ok-border);color:var(--ok-fg)}
.notice.warn{background:var(--warn-bg);border-color:var(--warn-border);color:var(--warn-fg)}
.notice.danger{background:var(--danger-bg);border-color:var(--danger-border);color:var(--danger)}

/* Hover explainer: the replacement for native title=. Put .tip and data-tip="..." on the element.
   It resets inherited text styles so a tooltip on a bold uppercase pill still reads as a sentence. */
.tip{position:relative}
.tip::after{
  content:attr(data-tip);
  position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);
  z-index:50;
  width:max-content;max-width:22em;white-space:pre-line;
  background:var(--surface-modal);color:var(--text);
  border:1px solid var(--border-modal);border-radius:var(--r-md);
  box-shadow:var(--shadow-pop);
  padding:.5em .7em;
  font-family:system-ui,sans-serif;font-size:.75rem;font-weight:400;font-style:normal;
  text-transform:none;letter-spacing:normal;text-align:left;line-height:1.45;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .12s ease-out}
/* Keyboard focus too: a hover-only explainer is invisible to keyboard users. */
.tip:hover::after,.tip:focus-visible::after{opacity:1;visibility:visible}
.tip:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;border-radius:var(--r-xs)}
.tip:not([data-tip])::after,.tip[data-tip=""]::after{content:none}

/* The in-page confirm dialog that the family's askConfirm script builds. */
dialog.family-confirm{border:1px solid var(--border-modal);border-radius:var(--r-lg);padding:0;
                      width:min(430px,92vw);box-shadow:var(--shadow-modal);
                      background:var(--surface-modal);color:var(--text)}
dialog.family-confirm::backdrop{background:var(--backdrop)}
.family-confirm .fc-body{padding:1.2em 1.25em 1.05em;white-space:pre-wrap;line-height:1.45;font-size:.95em}
.family-confirm .fc-actions{display:flex;justify-content:flex-end;gap:.5em;padding:.8em 1.1em 1em;
                            border-top:1px solid var(--border-subtle)}
/* A destructive confirmation is a solid fill, stronger than the tinted .btn.danger outline. */
.family-confirm .fc-ok.danger-solid{background:var(--danger-solid);border-color:var(--danger-solid-border);
                                    color:var(--on-solid)}
.family-confirm .fc-ok.danger-solid:hover{background:var(--danger-solid-border)}

/* Honour the OS reduced-motion setting: stop animation and transitions. .motion-live is exempt
   only for small motion that is never the sole carrier of its meaning (a status dot that also
   says its state in words). html.no-motion is the per-user switch and has no exemption. */
@media (prefers-reduced-motion: reduce){
  *:not(.motion-live),*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important}
}
html.no-motion *,html.no-motion *::before,html.no-motion *::after{
  animation-duration:.01ms !important;
  animation-iteration-count:1 !important;
  transition-duration:.01ms !important;
  scroll-behavior:auto !important}

/* Project identity tokens (fork-owned). --tool-accent is required in both blocks;
   any other token here takes a project-owned prefix and never redefines a family token. */
:root{--tool-accent:#b3161c}
html.dark-mode{--tool-accent:#ff6b6b}
/* The event screen (/screen): one look, no light theme, as the mockup the event team approved. */
:root{
  --evl-text:#F5F2EF;--evl-muted:#EDE6E3;--evl-edge:rgba(255,255,255,.6);--evl-edge-strong:rgba(255,255,255,.7);
  --evl-open:#7DF0A6;--evl-popup:#1B0D0E;--evl-red:#D91F26;--evl-on-red:#FFFFFF;
  --evl-live:#FF2D2D;--evl-live-dim:#8E0D0D;--evl-live-ring:rgba(0,0,0,.55);
  --evl-page:#0A0405;--evl-stage:#1A0405;--evl-shadow:rgba(0,0,0,.55);--evl-ticker:#000000;
  --evl-shade:rgba(5,2,3,.75);--evl-line:rgba(255,255,255,.25);--evl-line-soft:rgba(255,255,255,.35);
  --evl-line-mid:rgba(255,255,255,.5);--evl-tint:rgba(255,255,255,.08);--evl-dashed:rgba(255,255,255,.45);
  --evl-banner:rgba(20,8,9,.88);--evl-amber:#F2B84B;--evl-ink:#16090A;--evl-paper:#F5F2EF;--evl-hollow:#FFFFFF;
  --evl-head:"Space Grotesk","Segoe UI",sans-serif;--evl-body:Inter,"Segoe UI",sans-serif;
}
