/*
 * Dino Signal — the shared demo layer
 * ===========================================================================
 * ONE file. Every demo links it. When the brand palette moves, it moves here and
 * nowhere else — which is the whole reason this exists: before it, nine demos each carried
 * their own inline copy of the palette and their own duplicated dino-mark.jpg, so a brand
 * change meant nine edits and, in practice, meant the demos slowly drifting apart.
 *
 * WHAT THIS FILE OWNS
 *   the fossil palette · the shared type stacks · the demo ribbon · focus rings ·
 *   reduced-motion · touch-target and safe-area floors
 *
 * WHAT THIS FILE MUST NEVER OWN
 *   layout · grids · hero composition · section rhythm · component shapes
 *
 * That second list is not an oversight. Every demo has to look like a DIFFERENT studio built
 * it — a leather workshop and a tutorial centre share a brand family, not a template. Each
 * demo keeps its own layout, its own type pairing, its own motion, and its own accent, and
 * declares that accent by setting --accent on :root. If a rule here would make two demos look
 * alike, it belongs in the demo, not in this file.
 *
 * HOW A DEMO ADOPTS IT
 *   <link rel="stylesheet" href="_shared/fossil.css">
 *   :root { --accent: #8c5a3c; }       ← its own, from content/demos.ts
 *   then map its local token names onto the fossil scale below.
 */

/* ── Fonts, hosted once for every demo ─────────────────────────────────────
   Previously each demo carried its own copy: four woff2 in leather, three in kidsclothing,
   two in several others — the same files, downloaded again per demo. */

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/space-grotesk.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+2013-2014, U+2018-201A, U+201C-201E, U+2022, U+2026;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/inter.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+2013-2014, U+2018-201A, U+201C-201E, U+2022, U+2026;
}

@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/cinzel-600.woff2') format('woff2');
  unicode-range: U+0000-00FF;
}

/* The Traditional Chinese faces are SUBSETS — they carry the glyphs these demos actually use,
   not the whole family. A full Noto Serif TC is measured in megabytes and would dwarf every
   other asset on a demo page. */
@font-face {
  font-family: 'Noto Serif TC';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/notoseriftc-500-subset.woff2') format('woff2');
  unicode-range: U+3000-303F, U+4E00-9FFF, U+FF00-FFEF, U+30FB;
}

@font-face {
  font-family: 'Noto Serif TC';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/notoseriftc-600-subset.woff2') format('woff2');
  unicode-range: U+3000-303F, U+4E00-9FFF, U+FF00-FFEF, U+30FB;
}

/* ── The fossil scale ──────────────────────────────────────────────────────
   Identical to styles/tokens.css on the main site. Values, not aliases, because a static
   demo folder cannot import the @dinosignal/ui package — so this file is the copy, and it is
   the ONLY copy. */

:root {
  /* Signal — CTA, focus, active, one important word. Never a large fill. */
  --ds-signal: #fcba02;
  --ds-signal-600: #e0a500;
  --ds-signal-dim: rgba(252, 186, 2, 0.38);
  --ds-signal-ghost: rgba(252, 186, 2, 0.12);

  /* Matrix — the rock. Deepest ground. */
  --ds-matrix: #0e0b07;
  --ds-strata-900: #0e0b07;
  --ds-strata-850: #14100a;
  --ds-strata-800: #1b150d;
  --ds-strata-700: #251d12;
  --ds-strata-600: #33281a;
  --ds-strata-500: #453522;

  /* Bone — the excavated side. Warm; never pure white, which reads as a stock template. */
  --ds-bone-050: #fdfaf3;
  --ds-bone-100: #f5ecd7;
  --ds-bone-200: #e7dac0;
  --ds-bone-300: #c9b79a;
  --ds-bone-400: #a8977c;
  --ds-bone-500: #7d6e57;

  /* The mark. ADR-0023 — tan on matrix, and NOT interchangeable with the signal colour. */
  --ds-mark: #ab7f59;
  --ds-mark-ground: #0e0b07;

  /* Ink for reading, on either ground. */
  --ds-ink-on-dark: #f5ecd7;
  --ds-ink-on-dark-soft: #c9b79a;
  --ds-ink-on-light: #1a140d;
  --ds-ink-on-light-soft: #4a3f31;

  /* Each demo overrides this one line. It is the demo's identity inside the family. */
  --accent: var(--ds-mark);

  --ds-font-latin: 'Space Grotesk', 'Inter', system-ui, sans-serif;
  --ds-font-body: 'Inter', 'PingFang TC', 'Microsoft JhengHei', system-ui, sans-serif;
  --ds-font-cjk-serif: 'Noto Serif TC', 'Songti TC', serif;
  --ds-font-inscription: 'Cinzel', 'Times New Roman', serif;

  --ds-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ds-motion: 1;
}

/*
 * Reduced motion. Doubled selector deliberately: a demo's own `:root` block loads after this
 * file and would otherwise win on source order, silently re-enabling animation for someone who
 * asked for none.
 */
@media (prefers-reduced-motion: reduce) {
  :root:root {
    --ds-motion: 0;
  }

  html {
    scroll-behavior: auto !important;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ── The demo ribbon ───────────────────────────────────────────────────────
   Every demo says what it is, at the top, before anything else. These are fictional shops;
   a visitor who mistakes one for a real business has been misled, and a prospect who cannot
   tell it is a demo does not know they are looking at our work. */

.ds-demo-ribbon {
  position: relative;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0.5rem 1rem;
  padding-inline-start: max(1rem, env(safe-area-inset-left));
  padding-inline-end: max(1rem, env(safe-area-inset-right));
  background: var(--ds-matrix);
  color: var(--ds-ink-on-dark);
  font-family: var(--ds-font-body);
  font-size: 0.78rem;
  line-height: 1.45;
  letter-spacing: 0.02em;
  text-align: center;
  border-block-end: 1px solid rgba(201, 183, 154, 0.16);
}

.ds-demo-chip {
  /* Square, not a pill. A rounded chip is the single most template-looking element available. */
  background: var(--ds-signal);
  color: var(--ds-matrix);
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 0.12rem 0.5rem;
  border-radius: 2px;
  white-space: nowrap;
}

.ds-demo-ribbon a {
  color: var(--ds-signal);
  text-underline-offset: 3px;
}

.ds-demo-mark {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--ds-font-inscription);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.72rem;
  color: var(--ds-mark);
}

/* ── Floors every demo has to clear ────────────────────────────────────────
   Accessibility and mobile basics, applied once so no demo can quietly skip them. */

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--ds-signal);
  outline-offset: 2px;
  border-radius: 2px;
}

/* iOS Safari zooms the page when a focused input is under 16px. Every demo's form inherits
   this floor rather than each one remembering it. */
:where(input, select, textarea) {
  font-size: max(16px, 1em);
}

/* A tap target below 44px is a miss on a phone. */
:where(a, button)[data-tap] {
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
}

/* :hover latches after a tap on touch devices, leaving elements stuck in their hover state. */
@media (hover: none) {
  :where(a, button):hover {
    transition: none;
  }
}

img,
video {
  max-inline-size: 100%;
  block-size: auto;
}

/* ── Heading wrap ───────────────────────────────────────────────────────────
 * `text-wrap: balance` on headings only. This is typography, not layout, so it does not
 * breach the rule above about what this file may own — it changes where a line breaks, never
 * where a block sits.
 *
 * It matters more in Chinese than in English. CJK has no spaces, so a browser will break
 * between any two characters, and a heading like 先看時間表，再看課程。can end a line on 課 and
 * start the next on 程 — splitting a word in half. Balance distributes the characters across
 * lines instead, which keeps 課程 together far more often.
 *
 * Capped at 4 lines because balancing is O(n²) in the line count and browsers stop applying it
 * on long text anyway; headings are never that long.
 */
:where(h1, h2, h3) {
  text-wrap: balance;
}

/* Body copy gets `pretty` rather than `balance`: it avoids a one-word last line without
   re-flowing the whole paragraph. */
:where(p, li, dd) {
  text-wrap: pretty;
}

/* ── An SVG must not be wider than its container ────────────────────────────
 * `img, video { max-inline-size: 100% }` is a reflex; SVG is routinely left out of it, and an
 * inline <svg> with a viewBox but no width renders at its INTRINSIC size. The leather demo's
 * seam graphic is viewBox="0 0 1200 18", so it forced the whole document to 1200px and every
 * page below 1200 scrolled sideways — on a phone, that is the single most noticeable defect a
 * site can have, and nothing about the markup looks wrong.
 */
svg {
  max-inline-size: 100%;
}

/* ── Tap-target floor, continued ────────────────────────────────────────────
 * A demo's own nav links are typically one or two Chinese characters, which lands them at
 * 17–27px tall — a miss on a phone. The floor applies only where the pointer is a finger, so
 * desktop navigation keeps its compact signage rhythm.
 *
 * Labels get it too: a 16px checkbox is the correct size for the control, but the LABEL is what
 * a thumb aims at, and it is the label that has to be 44px.
 */
@media (pointer: coarse) {
  :where(header, nav, footer) :where(a, button) {
    min-block-size: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* NOT :where() inside the :has(). :has() takes the specificity of its argument, and
     :where() zeroes that out — leaving this rule at (0,0,1), which any demo's own
     `.rail label` (0,1,1) silently beats. Written plainly it lands at (0,1,2) and holds. */
  label:has(input[type='checkbox']),
  label:has(input[type='radio']) {
    min-block-size: 44px;
  }
}
