/* ============================================================================
   SWITCH + THEME SWITCH — single source of truth.
   Canonical component CSS shared by comp-switch.html (the spec/demo card),
   brand-header.html (the dark gov.cz strip), and any future consumer. Pair with
   _switch.js for the elastic drag/toggle controller.

   Variants:
     .sw                      boolean on/off switch (label + hidden checkbox + track)
     .tsw                     2-state theme switch (button[role=switch])  · 52×28
     .tsw--sm                 compact theme switch                         · 44×24
     .tsw--on-dark            theme switch on a dark surface (gov.cz strip) · 40×22
     .tsw3                    3-state theme switch (light · auto · dark)

   Tokens live in colors_and_type.css (@layer tokens) + _dark.css (@layer theme):
     --sw-* (boolean track), --tsw-bg/-bd/-puck-light/-puck-dark/-thumb-shadow.
   ============================================================================ */

/* Registered so the Web Animations API can INTERPOLATE them (unregistered
   custom props animate discretely). inherits:true so ::before (.sw thumb) and
   the child <i> glyphs (.tsw thumb) read the animated value. --*-p is the 0..1
   travel progress that also drives the theme-switch glyph cross-fade/rotation,
   keeping the glyph swap part of the SAME timeline as the thumb movement. */
@property --sw-x  { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --sw-sx { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --sw-sy { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --tsw-x  { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --tsw-sx { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --tsw-sy { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --tsw-p  { syntax: "<number>"; inherits: true; initial-value: 0; }

/* Token-classifier home: --tsw-p is an animation-progress number (0→1), driven
   by @property + JS; declare a plain-:root default so the DS classifier can read
   its @kind (annotations attach in a plain :root, not @property/@layer scopes). */
:root { --tsw-p: 0; /* @kind other */ }

/* =============================================================================
   SWITCH — boolean on/off setting. DSGCZ-aligned.

     • Track 40 × 22 px, pill radius.
     • Off: neutral-300 track. On: primary-500 track.
     • Thumb: 18 × 18 white circle, 2 px inset, subtle drop shadow.
     • 160 ms ease-out for both track colour and thumb position.
   ============================================================================= */
/* SWITCH is SELF-CONTAINED on the token model (notes/architecture.md): light
   token defaults in @layer tokens, dark re-value in @layer theme, rules in
   @layer components. There is NO .sw entry in _dark.css. Safe to fully layer —
   the only focus ring lives on .sw__track (a <span>, no global competitor); the
   hidden <input>'s own global :where(input):focus-visible ring is invisible
   (opacity:0), so unlike the .field input there's nothing to suppress. Dark =
   pure token revalue (off/hover/disabled track steps shift one notch; thumb
   stays a bright puck via --sw-thumb). */
@layer tokens {
  :root {
    --sw-track-off:       var(--gov-color-neutral-300);
    --sw-track-off-hover: var(--gov-color-neutral-400);
    --sw-track-disabled:  var(--gov-color-neutral-200);
    --sw-thumb:           #ffffff;
    --sw-thumb-shadow:    0 1px 2px rgba(12,24,56,0.22), 0 0 0 0.5px rgba(12,24,56,0.05);
  }
}
@layer theme {
  [data-theme="dark"] {
    --sw-track-off:       var(--gov-color-neutral-400);
    --sw-track-off-hover: var(--gov-color-neutral-500);
    --sw-track-disabled:  var(--gov-color-neutral-300);
    --sw-thumb:           #ebeef3;
    --sw-thumb-shadow:    0 1px 2px rgba(0,0,0,0.45);
  }
}
@layer components {
.sw {
  display: inline-flex; align-items: center; gap: 12px;
  font: 400 14px var(--font-sans); color: var(--color-fg-default);
  cursor: pointer; user-select: none;
}
.sw__track {
  position: relative;
  width: 40px; height: 22px;
  border-radius: 999px;
  background: var(--sw-track-off);
  flex: none;
  /* box-shadow joins the transition so the focus ring blooms when the
     sibling input gains :focus-visible. Spring easing comes from the
     focus rule further down. Pattern shared with comp-inputs / comp-buttons. */
  transition: background 160ms ease-out,
              box-shadow 140ms ease-out;
}
.sw__track::before {
  content: ""; position: absolute;
  top: 2px; left: 2px;
  width: 18px; height: 18px;
  border-radius: 999px;
  background: var(--sw-thumb);
  box-shadow: var(--sw-thumb-shadow);
  /* Position + squash/stretch are var-driven (--sw-x/sx/sy). For ENHANCED
     switches the JS owns those vars: drag sets them per-move, and toggles play
     a Web-Animations timeline over them (so the playground speed control's
     playbackRate + ?rm reduced-motion both apply). The base transform-
     transition is the no-JS fallback only; `.sw--js` (added on enhance) drops
     it so inline/WAA writes aren't double-tweened. box-shadow stays transitioned
     so the drag shadow fades. */
  transform: translateX(var(--sw-x, 0px)) scaleX(var(--sw-sx, 1)) scaleY(var(--sw-sy, 1));
  transform-origin: center center;
  transition: transform 160ms ease-out, box-shadow 180ms ease;
}
.sw--js .sw__track::before { transition: box-shadow 180ms ease; }
.sw input:checked + .sw__track { --sw-x: 18px; }
.sw input { position: absolute; opacity: 0; pointer-events: none; }
.sw input:checked + .sw__track { background: var(--gov-color-primary-500); }
.sw input:checked + .sw__track::before { /* position now via --sw-x; see above */ }
/* Hover — track steps one notch darker (off → --sw-track-off-hover, on →
   primary-600 which flips on its own). Scoped :not(.sw--disabled) so disabled
   never reacts; [data-state="hover"] mirrors :hover so the focus playground +
   the static state-matrix below can force the look without a real pointer. */
.sw:not(.sw--disabled):hover .sw__track,
.sw:not(.sw--disabled)[data-state="hover"] .sw__track { background: var(--sw-track-off-hover); }
.sw:not(.sw--disabled):hover input:checked + .sw__track,
.sw:not(.sw--disabled)[data-state="hover"] input:checked + .sw__track { background: var(--gov-color-primary-600); }
.sw input:focus-visible + .sw__track,
.sw.is-focus .sw__track {
  box-shadow: var(--shadow-focus);
  /* Focus-ring bloom — pattern shared with comp-inputs / comp-buttons. */
  transition: background 160ms ease-out,
              box-shadow 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.sw--disabled { color: var(--color-fg-tertiary); cursor: not-allowed; opacity: 0.55; }
.sw--disabled .sw__track { background: var(--sw-track-disabled); cursor: not-allowed; }
/* Drag affordance: the thumb lifts a slightly deeper shadow WHILE dragging only
   (not on keyboard/click toggles), and it fades via the box-shadow transition
   above rather than snapping. */
.sw.is-drag .sw__track::before {
  box-shadow: 0 2px 7px rgba(12,24,56,0.30), 0 0 0 0.5px rgba(12,24,56,0.06);
}
/* grab/grabbing cursors only off Windows (Windows lacks native grab cursors —
   browsers fall back to blurry placeholders), so Windows keeps the plain
   pointer. The `is-win` class is set from JS via the UA platform. */
html:not(.is-win) .sw__track { cursor: grab; }
html:not(.is-win) .sw.is-grab, html:not(.is-win) .sw.is-grab .sw__track { cursor: grabbing; }
.sw--disabled .sw__track, html:not(.is-win) .sw--disabled .sw__track { cursor: not-allowed; }
}

/* =============================================================================
   THEME SWITCH — variant of switch carrying icon on the thumb.

     • Track is *always* neutral (theme is not "on/off" — it's a mode).
     • Sun ↔ moon icon lives ON the thumb. Icons cross-fade as the
       thumb slides.
     • 200 ms ease-out for the slide; 160 ms for icon opacity.

   Built as a single <button role="switch"> with aria-checked = "true"
   when dark. The 3-state variant below uses role="radiogroup" and
   places the active icon on a centred or offset thumb.
   ============================================================================= */
.tsw {
  position: relative;
  width: 52px; height: 28px;
  border-radius: 999px;
  border: 1px solid var(--tsw-bd);
  background: var(--tsw-bg);
  padding: 0;
  cursor: pointer;
  flex: none;
  transition: background 160ms ease-out, border-color 160ms ease-out,
              box-shadow 140ms ease-out;
}
/* Hover — track fills one neutral step + a stronger border. The mode track is
   always neutral, so hover is a quiet surface lift (not a colour change).
   Scoped so disabled never reacts; [data-state="hover"] mirrors :hover. */
.tsw:not(:disabled):not(.tsw--disabled):hover,
.tsw:not(:disabled):not(.tsw--disabled)[data-state="hover"] {
  background: var(--gov-color-neutral-200);
  border-color: var(--color-border-strong);
}
.tsw:focus-visible, .tsw.is-focus {
  outline: 0; box-shadow: var(--shadow-focus);
  /* Focus-ring bloom — system two-tier transition (140 ms exit / 220 ms entry). */
  transition: background 160ms ease-out, border-color 140ms ease-out,
              box-shadow 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.tsw--disabled, .tsw:disabled { opacity: 0.55; cursor: not-allowed; }
.tsw__thumb {
  position: absolute; top: 2px; left: 2px;
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--tsw-puck-light);
  box-shadow: var(--tsw-thumb-shadow);
  display: flex; align-items: center; justify-content: center;
  color: var(--tsw-puck-dark);
  cursor: pointer;
  /* Var-driven (--tsw-x/sx/sy). Enhanced switches get `.tsw--js` which drops the
     transform transition so the JS-owned drag + WAA toggle timeline aren't
     double-tweened; box-shadow stays transitioned so the drag shadow fades. */
  transform: translateX(var(--tsw-x, 0px)) scaleX(var(--tsw-sx, 1)) scaleY(var(--tsw-sy, 1));
  transform-origin: center center;
  transition: transform 200ms cubic-bezier(.4,.0,.2,1), background 160ms ease-out, color 160ms ease-out, box-shadow 180ms ease;
}
.tsw--js .tsw__thumb { transition: background 160ms ease-out, color 160ms ease-out, box-shadow 180ms ease; }
html:not(.is-win) .tsw__thumb { cursor: grab; }
/* Glyphs are centred via inset:0 + grid so rotation pivots on the true centre
   (fixes the ~1px vertical drift). Opacity + rotation are driven by --tsw-p —
   the SAME 0..1 progress that moves the thumb — so the sun↔moon swap is part of
   the thumb movement, not an independent transition. */
.tsw__thumb i {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 13px; line-height: 1;
}
.tsw__thumb .bi-sun-fill        { opacity: calc(1 - var(--tsw-p)); transform: rotate(calc(var(--tsw-p) * 90deg)); }
.tsw__thumb .bi-moon-stars-fill { opacity: var(--tsw-p);          transform: rotate(calc((var(--tsw-p) - 1) * 90deg)); }
/* Resting position/progress vars live on the .tsw BUTTON — the SAME element the
   JS writes inline vars on — so inline overrides them during a toggle/drag and
   the thumb interpolates instead of jumping. (If these sat on .tsw__thumb, a
   value specified directly on the thumb would beat the inline value inherited
   from the parent, snapping --tsw-x to the end instantly. inherits:true on the
   @property carries them down to the thumb + glyphs.) Colour stays on the thumb. */
.tsw[aria-checked="true"] { --tsw-x: 22px; --tsw-p: 1; /* @kind other */ }
.tsw[aria-checked="true"] .tsw__thumb { background: var(--tsw-puck-dark); color: var(--tsw-puck-light); }

/* Compact variant — used in dense surfaces like the state header */
.tsw--sm { width: 44px; height: 24px; }
.tsw--sm .tsw__thumb { width: 18px; height: 18px; }
.tsw--sm .tsw__thumb i { font-size: 11px; }
.tsw--sm[aria-checked="true"] { --tsw-x: 20px; }

/* On-dark variant — theme switch sitting on a dark surface (the gov.cz strip in
   brand-header.html / the prototype's .bar). 40×22 with a 16px puck; the track
   borrows white-alpha border/fill + a white focus ring so it reads on black,
   while the puck keeps the shared --tsw-puck-* colours (light puck + dark icon
   unchecked → dark puck + light icon checked, legible in both page themes).
   Defined after the base so its same-specificity rules win by source order. */
.tsw--on-dark {
  width: 40px; height: 22px;
  border-color: rgba(255,255,255,0.30);
  background: rgba(255,255,255,0.10);
}
.tsw--on-dark:not(:disabled):not(.tsw--disabled):hover,
.tsw--on-dark:not(:disabled):not(.tsw--disabled)[data-state="hover"] {
  background: rgba(255,255,255,0.18);
  border-color: rgba(255,255,255,0.55);
}
.tsw--on-dark:focus-visible, .tsw--on-dark.is-focus { box-shadow: 0 0 0 2px rgba(255,255,255,0.6); }
.tsw--on-dark .tsw__thumb { width: 16px; height: 16px; }
.tsw--on-dark .tsw__thumb i { font-size: 10px; }
.tsw--on-dark[aria-checked="true"] { --tsw-x: 18px; }

/* Drag affordance: deeper shadow WHILE dragging only, fading via the thumb's
   box-shadow transition. */
.tsw.is-drag .tsw__thumb { box-shadow: 0 2px 8px rgba(12,24,56,0.34), 0 0 0 0.5px rgba(12,24,56,0.06); }
html:not(.is-win) .tsw.is-grab, html:not(.is-win) .tsw.is-grab .tsw__thumb { cursor: grabbing; }
.tsw:disabled .tsw__thumb, .tsw--disabled .tsw__thumb { cursor: not-allowed; }

/* 3-state variant: light · auto · dark. The thumb has three rest
   positions and the icon swaps on each. Implemented with
   data-mode = "light" | "auto" | "dark". */
.tsw3 {
  position: relative;
  width: 80px; height: 28px;
  border-radius: 999px;
  border: 1px solid var(--tsw-bd);
  background: var(--tsw-bg);
  padding: 0;
  cursor: pointer;
  flex: none;
  display: flex; align-items: center; justify-content: space-around;
  transition: background 160ms ease-out, border-color 160ms ease-out,
              box-shadow 140ms ease-out;
}
.tsw3:not(:disabled):not(.tsw3--disabled):hover,
.tsw3:not(:disabled):not(.tsw3--disabled)[data-state="hover"] {
  background: var(--gov-color-neutral-200);
  border-color: var(--color-border-strong);
}
.tsw3:focus-visible, .tsw3.is-focus {
  outline: 0; box-shadow: var(--shadow-focus);
  transition: background 160ms ease-out, border-color 140ms ease-out,
              box-shadow 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.tsw3--disabled, .tsw3:disabled { opacity: 0.55; cursor: not-allowed; }
.tsw3 .tsw3__ico {
  width: 24px; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--color-fg-tertiary);
  position: relative; z-index: 1;
  transition: color 160ms ease-out;
}
.tsw3 .tsw3__thumb {
  position: absolute;
  top: 2px;
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--tsw-puck-light);
  box-shadow: var(--tsw-thumb-shadow);
  transition: left 200ms cubic-bezier(.4,.0,.2,1), background 160ms ease-out;
  z-index: 0;
}
.tsw3[data-mode="light"] .tsw3__thumb { left: 2px; }
.tsw3[data-mode="auto"]  .tsw3__thumb { left: 28px; }
.tsw3[data-mode="dark"]  .tsw3__thumb { left: 55px; background: var(--tsw-puck-dark); }
.tsw3[data-mode="light"] .tsw3__ico[data-mode="light"],
.tsw3[data-mode="auto"]  .tsw3__ico[data-mode="auto"]  { color: var(--tsw-puck-dark); }
.tsw3[data-mode="dark"]  .tsw3__ico[data-mode="dark"]  { color: var(--tsw-puck-light); }
