/* Fonts ship with the app (SIL Open Font License, see fonts/OFL-*.txt), so it looks right
   offline from the first launch and makes no requests to a font service. Both are
   variable fonts covering the weight ranges below. */
@font-face{
  font-family:'Orbitron'; font-style:normal; font-weight:700 900; font-display:swap;
  src:url(fonts/orbitron-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Space Grotesk'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url(fonts/space-grotesk-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Space Grotesk'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url(fonts/space-grotesk-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root{
  --bg:#0a0d12;
  --bg-panel:#10141b;
  --text:#f5f7fa;
  --text-dim:#8b94a3;
  --accent:#ffb454;
  --accent2:#5ec9f1;
  --divider:rgba(255,255,255,0.09);
  --shadow:rgba(0,0,0,0.4);
  /* Set from JS once the fonts load (see measureTime in app.js): width of the widest
     "HH:MM" per 1em of font size, and the time row's height per 1em. */
  --time-ratio:3.6;
  --cap:0.73;
}
@media (prefers-color-scheme: light){
  :root{
    --bg:#f4f2ec;
    --bg-panel:#ffffff;
    --text:#14181f;
    --text-dim:#5b6270;
    --accent:#c2740f;
    --accent2:#0f7ea8;
    --divider:rgba(0,0,0,0.08);
    --shadow:rgba(0,0,0,0.12);
  }
}
:root{ color-scheme:dark light; }
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0a0d12; --bg-panel:#10141b; --text:#f5f7fa; --text-dim:#8b94a3;
  --accent:#ffb454; --accent2:#5ec9f1; --divider:rgba(255,255,255,0.09); --shadow:rgba(0,0,0,0.4);
}
:root[data-theme="light"]{
  color-scheme:light;
  --bg:#f4f2ec; --bg-panel:#ffffff; --text:#14181f; --text-dim:#5b6270;
  --accent:#c2740f; --accent2:#0f7ea8; --divider:rgba(0,0,0,0.08); --shadow:rgba(0,0,0,0.12);
}

*{box-sizing:border-box;}
[hidden]{display:none !important;}
/* The background is the page's own (html), so the screen fill (z-index -1) can sit between
   it and everything else. */
html{ background:var(--bg); }
html,body{
  margin:0; padding:0; height:100%; width:100%;
  color:var(--text);
  overflow:hidden;
  font-family:'Space Grotesk',system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
}
button{ font:inherit; color:inherit; }

/* Installed app with the title bar hidden (window-controls-overlay): this strip stands in
   for the title bar so the window can still be dragged. The env() values only exist in
   that mode; everywhere else the strip has zero height. Only the strip is draggable:
   a drag region swallows mouse events, so making the whole clock draggable would break
   hover on the tools. */
.titlebar{
  position:fixed;
  left:env(titlebar-area-x, 0); top:env(titlebar-area-y, 0);
  width:env(titlebar-area-width, 100%); height:env(titlebar-area-height, 0px);
  app-region:drag; -webkit-app-region:drag;
}

/* Layout model. The old version gave the time row a fixed 65% of the height; the digits
   are almost always width-bound, so that row carried empty bands above and below them,
   and the weather cells were fixed-width columns with their own dead space.
   Now: the time row is exactly as tall as the digits (sized from .app's width/height),
   the weather band is scaled by JS (fitBand in app.js) to the largest size that fits the
   space left over, and whatever space remains is shared evenly above, between and below
   the rows (space-evenly), so it reads as margin rather than as holes. */
.app{
  height:100vh; width:100vw;
  padding:
    calc(env(titlebar-area-height, 0px) + clamp(0.3rem, 1.5vh, 1rem))
    clamp(0.6rem, 2.6vw, 2rem)
    clamp(0.3rem, 1.5vh, 1rem);
  container-type:size; container-name:app;
}
.primary{
  height:100%; width:100%;
  display:grid;
  grid-template-columns:minmax(0,1fr);
  /* Implicit rows only: an explicit empty track (no timer running) would count as one
     more row in space-evenly and leave a double gap at the bottom. */
  grid-auto-rows:auto;
  align-content:space-evenly;
}
/* --tsize: the digits fill the width (cqw / ratio) unless that would make them taller
   than their share of the height (cqh / cap), whichever is smaller. --tfit (set by
   fitLayout in app.js) stays 1 unless the weather and timers need some of that share. */
:root[data-layout="row"] .primary{ --tsize:calc(min(calc(97cqw / (var(--time-ratio) + 2 * var(--ring-x, 0))), calc(52cqh / (var(--cap) + 2 * var(--ring-y, 0)))) * var(--tfit, 1)); }
:root[data-layout="stack"] .primary{ --tsize:calc(min(calc(95cqw / (var(--time-ratio) + 2 * var(--ring-x, 0))), calc(32cqh / (var(--cap) + 2 * var(--ring-y, 0)))) * var(--tfit, 1)); }
/* --ring-x / --ring-y: the race ring's margins around the digits, in em, set by app.js while
   the ring shows (0 otherwise), so the digits shrink just enough to make room for it. */

/* ---------- time ---------- */
.time{
  justify-self:center; position:relative;
  display:flex; align-items:center; justify-content:center;
  font-family:'Orbitron',sans-serif;
  font-weight:900;
  font-size:var(--tsize);
  line-height:1;
  letter-spacing:0.01em;
  color:var(--accent);
  font-variant-numeric:tabular-nums;
  text-shadow:0 0.03em 0.15em var(--shadow);
  white-space:nowrap;
}
/* Trim the line box to the digits themselves, so the row's height is the digits' height
   with no built-in space above the caps or below the baseline. */
.time .hh, .time .mm{ text-box:trim-both cap alphabetic; }
@supports not (text-box: trim-both cap alphabetic){
  .time .hh, .time .mm{ line-height:0.76; }
}
/* Off-screen copy at a fixed size, used only to measure --time-ratio / --cap. */
.time.measure{ position:absolute; left:-10000px; top:0; visibility:hidden; font-size:100px; }
.time.measure .ring{ display:none; }

/* Colon is a small widget, not a glyph: dots with the live seconds between them, and
   (in 12h mode) the am/pm tag below, so neither costs horizontal space. In 12h mode it
   is taller than the digits and sets the row height (--cap is measured to match). */
.colon{
  display:flex; flex-direction:column; align-items:center; justify-content:space-between;
  height:0.56em; width:0.42em;
  margin:0 0.05em;
}
.colon.has-ampm{ height:0.9em; }
.colon .dot{
  display:block; width:0.15em; height:0.15em; border-radius:15%;
  background:var(--accent); flex-shrink:0;
  animation:blink 2s steps(1) infinite;
}
.colon .csec{
  font-family:'Space Grotesk',sans-serif; font-weight:700; font-style:normal;
  font-size:0.16em; line-height:1; color:var(--text-dim);
  font-variant-numeric:tabular-nums;
}
.colon .cap{
  font-family:'Space Grotesk',sans-serif; font-weight:800; font-style:normal;
  font-size:0.15em; line-height:1; color:var(--accent); opacity:0.9;
  letter-spacing:0.02em;
}
@keyframes blink{ 0%,49%{opacity:1;} 50%,100%{opacity:0.25;} }
/* Seconds round the clock instead: the digits make way (keeping their space). */
:root[data-seconds="ring"] .colon .csec{ visibility:hidden; }

/* ---------- race ring ----------
   A faint track around the digits, finish at 12 o'clock under a small triangle; running
   timers race round it (renderRing in app.js). The time's box grows by the ring's margins,
   so the ring is exactly that box. Racers are placed in % of it; their size is in em of the
   digits (.ti is 1.6em of a racer's 0.125em: a fifth of the digits' height). */
:root[data-ring] .time:not(.measure){
  padding:calc(var(--ring-y) * 1em) calc(var(--ring-x) * 1em);
  min-width:calc((var(--time-ratio) + 2 * var(--ring-x)) * 1em);
}
.ring{ display:none; position:absolute; inset:0; pointer-events:none; }
:root[data-ring] .time:not(.measure) .ring{ display:block; }
.ring .track{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.track-line{ fill:none; stroke:var(--text-dim); stroke-opacity:0.28; stroke-width:1.5px; vector-effect:non-scaling-stroke; }
.bezel{ fill:var(--text-dim); fill-opacity:0.75; }
.racer{
  position:absolute; font-size:0.125em; line-height:0;
  padding:0.12em; border-radius:50%;
  transform:translate(-50%, -50%);
  pointer-events:auto; cursor:pointer;
  transition:transform 0.28s cubic-bezier(0.3, 1.4, 0.5, 1), box-shadow 0.28s, background-color 0.28s;
}
.racer .ti{ display:block; }
.racer.far{ opacity:0.4; }
.racer.paused .ti-level{ color:var(--text-dim); }
.racer.done .ti-level{ color:var(--accent); }
.racer.done .ti{ animation:pop 0.9s ease-in-out infinite; transform-origin:50% 70%; }
/* Point at a racer and it grows in place, keeping its level. */
.racer:hover{ transform:translate(-50%, -50%) scale(2.4); z-index:2; opacity:1; background:var(--bg-panel); box-shadow:0 0.15em 0.5em var(--shadow); }
.sec-hand{
  position:absolute; width:0.05em; height:0.05em; margin:-0.025em 0 0 -0.025em;
  border-radius:50%; background:var(--accent);
}

/* ---------- screen fill ----------
   Behind everything: a faint wash that empties with the timer that ends next, with that
   timer's icon floating just under the surface. */
.fill{ position:fixed; inset:0; z-index:-1; pointer-events:none; }
.fill-level{
  position:absolute; left:0; right:0; bottom:0; overflow:hidden;
  background:color-mix(in srgb, var(--accent2) 7%, transparent);
  border-top:1px solid color-mix(in srgb, var(--accent2) 30%, transparent);
}
/* (No transition: the level moves well under a pixel a second, and animating it would
   redraw the whole window every frame.) */
.fill.paused .fill-level{ background:color-mix(in srgb, var(--text-dim) 6%, transparent); border-top-color:color-mix(in srgb, var(--text-dim) 25%, transparent); }
.fill.done .fill-level{ background:color-mix(in srgb, var(--accent) 8%, transparent); border-top-color:color-mix(in srgb, var(--accent) 35%, transparent); }
.fill .buoy{ position:absolute; left:1.2rem; top:0.35rem; width:1.3rem; height:1.3rem; color:var(--accent2); opacity:0.6; }
.fill.paused .buoy{ color:var(--text-dim); }
.fill.done .buoy{ color:var(--accent); }

/* Quiet hours: the screen dims (the settings and pop-ups stay bright). */
:root[data-quiet] body::after{ content:""; position:fixed; inset:0; z-index:15; background:#000; opacity:0.45; pointer-events:none; }

/* ---------- weather band ----------
   Everything inside is sized in em of the band's font-size, which fitBand() sets so the
   whole band is as large as the leftover space allows. Icons are deliberately tall
   relative to the text: the band is usually width-bound, and taller icons use height
   that would otherwise go unused. */
.band{ font-size:16px; min-width:0; }
.now{ display:flex; flex-direction:column; align-items:center; gap:0.3em; }
.now svg{ width:5.2em; height:5.2em; color:var(--accent2); flex-shrink:0; }
.now .temp{ font-family:'Orbitron',sans-serif; font-weight:700; line-height:1; font-size:2.4em; color:var(--text); }
.info{ display:flex; flex-direction:column; align-items:flex-start; gap:0.4em; min-width:0; text-align:left; }
.date{ font-size:1.05em; font-weight:600; color:var(--text-dim); letter-spacing:0.02em; white-space:nowrap; }
.cond{ font-size:1.9em; font-weight:600; line-height:1.05; color:var(--text-dim); white-space:nowrap; }
.hilo-row{ display:flex; align-items:baseline; min-width:0; font-size:0.95em; color:var(--text-dim); white-space:nowrap; }
/* The place is a geocoded name with no length guarantee: truncate, never push. */
.hilo-row .place{ opacity:0.7; overflow:hidden; text-overflow:ellipsis; max-width:12em; }
.hilo-row .place::before{ content:" · "; opacity:0.6; white-space:pre; }
.forecast{ display:flex; align-items:center; gap:1.6em; }
.day{ display:flex; flex-direction:column; align-items:center; gap:0.35em; }
.day .d{ font-size:0.95em; font-weight:700; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.05em; }
.day svg{ width:3.4em; height:3.4em; color:var(--accent2); }
.day .t{ font-size:1.1em; font-weight:700; font-variant-numeric:tabular-nums; color:var(--text); }
.day .t small{ color:var(--text-dim); }

/* Weather switched off (Settings > Show): the date only. */
.band.date-only .now, .band.date-only .cond, .band.date-only .hilo-row,
.band.date-only .forecast, .band.date-only .weather-status{ display:none !important; }
/* Just the date: no grid (its empty rows would still add gaps the layout fit doesn't count). */
.band.date-only, :root[data-layout="stack"] .band.date-only{ display:flex; justify-content:center; }
.band.date-only .date{ margin-bottom:0; }

/* Point at the weather and it comes alive (Motion: Full only): sun rays turn, clouds drift,
   rain and snow fall, the moon rocks, lightning flickers. Calm the rest of the time. */
.band .w-spin, .band .w-rock{ transform-box:fill-box; transform-origin:center; }
.band .w-spin-small{ transform-box:view-box; transform-origin:7px 7.5px; }
:root[data-motion="full"] .band:hover .w-spin, :root[data-motion="full"] .band:hover .w-spin-small{ animation:w-spin 8s linear infinite; }
:root[data-motion="full"] .band:hover .w-drift{ animation:w-drift 3s ease-in-out infinite; }
:root[data-motion="full"] .band:hover .w-fall{ animation:w-fall 1s linear infinite; }
:root[data-motion="full"] .band:hover .w-rock{ animation:w-rock 3s ease-in-out infinite; }
:root[data-motion="full"] .band:hover .w-flash{ animation:w-flash 2.2s steps(1) infinite; }
:root[data-motion="full"] .band:hover .w-d2{ animation-delay:-0.33s; }
:root[data-motion="full"] .band:hover .w-d3{ animation-delay:-0.66s; }
@keyframes w-spin{ to{ transform:rotate(360deg); } }
@keyframes w-drift{ 0%,100%{ transform:translateX(0); } 50%{ transform:translateX(1.2px); } }
@keyframes w-fall{ 0%{ transform:translateY(-2px); opacity:0; } 30%{ opacity:1; } 100%{ transform:translateY(2.5px); opacity:0; } }
@keyframes w-rock{ 0%,100%{ transform:rotate(-7deg); } 50%{ transform:rotate(7deg); } }
@keyframes w-flash{ 0%,100%{ opacity:1; } 8%{ opacity:0.2; } 12%{ opacity:1; } 16%{ opacity:0.3; } 20%{ opacity:1; } }

/* No weather yet (loading, no location, offline with no cache): only the date and a
   status line remain. */
.weather-status{ display:none; }
.band.no-data .now, .band.no-data .cond, .band.no-data .hilo-row, .band.no-data .forecast{ display:none; }
.band.no-data .weather-status{ display:flex; align-items:center; gap:0.6em; flex-wrap:wrap; font-size:1.1em; color:var(--text-dim); }
.weather-status button{
  background:none; border:1px solid var(--divider); color:var(--text-dim);
  border-radius:1em; padding:0.3em 0.9em; cursor:pointer;
}
.weather-status button:hover{ color:var(--text); border-color:var(--accent2); }

/* Split (wide windows): now | info | forecast in one row, edge to edge under the time;
   spare width goes evenly between the three groups. */
:root[data-layout="row"] .band{ display:flex; align-items:center; justify-content:space-between; gap:2.4em; }
:root[data-layout="row"] .band.no-data{ justify-content:center; }
:root[data-layout="row"] .date .year{ display:none; }
/* While fitBand measures, pack the groups at their minimum gaps. */
.band.measuring{ width:max-content; justify-content:flex-start; }
.band.measuring > *{ flex-shrink:0; }

/* Stacked (portrait / squarer windows): .info dissolves (display:contents) so the date
   gets its own line and conditions + high/low pair up with the temperature. */
:root[data-layout="stack"] .band{
  display:grid;
  grid-template-columns:auto auto;
  grid-template-areas:"date date" "now cond" "now hilo" "fc fc" "status status";
  justify-content:center; justify-items:center;
  column-gap:1.6em; row-gap:0.7em;
}
:root[data-layout="stack"] .info{ display:contents; }
:root[data-layout="stack"] .date{ grid-area:date; font-size:1.3em; margin-bottom:0.4em; }
:root[data-layout="stack"] .now{ grid-area:now; }
:root[data-layout="stack"] .now svg{ width:4.4em; height:4.4em; }
:root[data-layout="stack"] .now .temp{ font-size:2.2em; }
:root[data-layout="stack"] .cond{ grid-area:cond; align-self:end; justify-self:start; font-size:2em; }
:root[data-layout="stack"] .hilo-row{ grid-area:hilo; align-self:start; justify-self:start; font-size:1.05em; }
:root[data-layout="stack"] .forecast{ grid-area:fc; gap:2em; margin-top:0.8em; }
:root[data-layout="stack"] .day svg{ width:3em; height:3em; }
:root[data-layout="stack"] .day .t{ font-size:1.15em; }
:root[data-layout="stack"] .weather-status{ grid-area:status; }

/* ---------- running timers ----------
   The row only exists while a timer runs (hidden otherwise), so it costs no space.
   Everything is in em; fitLayout in app.js sets the font size so the pills fit with the
   time and weather, wrapping onto more lines when the window is narrow. */
.timers{
  display:flex; flex-wrap:wrap; justify-content:center; gap:0.6em;
  font-size:min(1.5rem, 1.8cqw);
}
/* While fitLayout measures: each pill at its natural width, on one line. */
.timers.measuring{ width:max-content; flex-wrap:nowrap; }
.timer{
  display:flex; align-items:center; gap:0.6em;
  padding:0.3em 0.35em 0.3em 0.45em;
  border:1px solid var(--divider); border-radius:999px;
  background:var(--bg-panel);
}
.timer .tl{ color:var(--text-dim); font-weight:600; white-space:nowrap; }
.timer .tr{
  font-family:'Orbitron',sans-serif; font-weight:700;
  color:var(--accent2); font-variant-numeric:tabular-nums;
}
/* The draining icon (drainEl in app.js): the outline, and a coloured copy in a box anchored
   to the bottom whose height is the time left, so the colour drains from the top. */
.ti{ position:relative; width:1.6em; height:1.6em; flex-shrink:0; }
.ti-base{ position:absolute; inset:0; color:var(--text-dim); opacity:0.5; }
.ti-level{ position:absolute; left:0; right:0; bottom:0; height:100%; overflow:hidden; color:var(--accent2); }
.ti-fill{ position:absolute; left:0; bottom:0; width:1.6em; height:1.6em; }
.ti-base, .ti-fill, .ci{ display:block; }
.ti svg, .ci svg{ display:block; width:100%; height:100%; }
.ti img, .ci img{ display:block; width:100%; height:100%; border-radius:50%; object-fit:cover; }
.ti-base.photo img{ filter:grayscale(1); }
.timer.paused .ti-level{ color:var(--text-dim); }
.timer.done .ti-level{ color:var(--accent); }
.timer.done .ti{ animation:pop 0.9s ease-in-out infinite; transform-origin:50% 70%; }
@keyframes pop{ 0%,100%{ transform:scale(1); } 40%{ transform:scale(1.2) rotate(-6deg); } 70%{ transform:scale(0.95) rotate(3deg); } }
/* The icon is a button: it opens the timer's card. Pointing at it grows it in place,
   keeping its level, on a disc so it reads over whatever is behind. */
.tico{
  position:relative; display:block; flex-shrink:0; padding:0; margin:0;
  background:none; border:none; border-radius:50%; cursor:pointer;
  transform-origin:50% 85%;
  transition:transform 0.28s cubic-bezier(0.3, 1.4, 0.5, 1), box-shadow 0.28s, background-color 0.28s;
}
.tico .ti{ display:block; }
.tico:hover, .tico:focus-visible{ transform:scale(3.2); z-index:3; background:var(--bg-panel); box-shadow:0 0.2em 0.6em var(--shadow); }
/* A small, coloured timer icon: quick-timer chips and the settings rows. */
.ci{ width:1.2em; height:1.2em; flex-shrink:0; color:var(--accent2); }
.tbtn{
  width:1.8em; height:1.8em; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:none; border:none; border-radius:50%;
  color:var(--text-dim); cursor:pointer;
}
.tbtn:hover{ background:var(--divider); color:var(--text); }
.tbtn svg{ width:0.95em; height:0.95em; }
.tbtn.rep{ opacity:0.55; }
.tbtn.rep[aria-pressed="true"]{ opacity:1; color:var(--accent2); }
/* The next alarm, after the timers: a button that opens the alarm settings. */
.alarm-pill{ cursor:pointer; padding:0.3em 0.95em 0.3em 0.55em; }
.alarm-pill .ci{ width:1.4em; height:1.4em; color:var(--accent); }
.alarm-pill .tr{ color:var(--text); }
.alarm-pill:hover{ border-color:var(--accent2); }
.timer.paused .tr{ color:var(--text-dim); }
.timer.done{ border-color:var(--accent); animation:pulse 1.4s ease-in-out infinite; }
.timer.done .tl, .timer.done .tr{ color:var(--accent); }
@keyframes pulse{
  0%,100%{ box-shadow:0 0 0 0 transparent; }
  50%{ box-shadow:0 0 0 0.3em color-mix(in srgb, var(--accent) 25%, transparent); }
}

/* ---------- tools: quick timers + settings ----------
   Top-right corner; in the title-bar-less app they sit inside the title strip, just left
   of the window buttons. The preset chips appear while pointing at the stopwatch (or
   after a click on it, for touch), so the clock stays clean the rest of the time. */
.tools{
  position:fixed; z-index:20;
  top:env(titlebar-area-y, 0.4rem);
  right:calc(100vw - env(titlebar-area-x, 0px) - env(titlebar-area-width, 100vw) + 0.4rem);
  height:env(titlebar-area-height, 2rem);
  display:flex; align-items:center;
  app-region:no-drag; -webkit-app-region:no-drag;
}
.tool{
  width:2rem; height:2rem; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:none; border:none; border-radius:50%;
  color:var(--text-dim);
  cursor:pointer; opacity:0.35; transition:opacity 0.15s;
}
.tool:hover, .tool:focus-visible, .tools.open #timer-btn, .panel-open #gear{ opacity:0.9; }
.tool svg{ width:1.15rem; height:1.15rem; }
.quick{ display:none; align-items:center; gap:0.3rem; padding-right:0.3rem; }
.tools:has(#timer-btn:hover) .quick, .quick:hover, .tools.open .quick, .tools:has(.quick :focus-visible) .quick{ display:flex; }
/* When the chips don't fit in a row left of the icons (narrow windows), fitQuick in
   app.js drops them into a column under the stopwatch, scaled down if it's too tall. */
.tools.quick-col .quick{
  position:absolute; top:100%; right:2rem;
  flex-direction:column; align-items:flex-end;
  padding:0.3rem 0 0; transform-origin:top right;
}
.tools.measure-quick .quick{ display:flex; visibility:hidden; }
.chip{
  display:inline-flex; align-items:center; gap:0.35em;
  background:var(--bg-panel); border:1px solid var(--divider); color:var(--text);
  border-radius:999px; padding:0.25rem 0.65rem 0.25rem 0.45rem;
  font-size:0.78rem; font-weight:600; white-space:nowrap; cursor:pointer;
}
.chip:hover{ border-color:var(--accent2); }
.chip small{ color:var(--text-dim); font-weight:500; font-size:1em; }

/* ---------- settings panel ----------
   Always fits the window, with nothing to scroll: fitPanel in app.js picks one column or
   two side by side (wide, short windows), then scales the panel down from its top-right
   corner only as much as the window needs. */
.panel{
  position:fixed; z-index:30;
  top:calc(env(titlebar-area-y, 0px) + env(titlebar-area-height, 2.4rem) + 0.3rem);
  right:calc(100vw - env(titlebar-area-x, 0px) - env(titlebar-area-width, 100vw) + 0.4rem);
  background:var(--bg-panel); border:1px solid var(--divider);
  border-radius:0.8rem; padding:0.9rem 1rem;
  display:none; flex-direction:column; gap:0.75rem;
  width:19.5rem;
  transform-origin:top right;
  box-shadow:0 0.5rem 1.5rem var(--shadow);
  text-align:left;
  font-size:0.85rem; color:var(--text-dim);
  app-region:no-drag; -webkit-app-region:no-drag;
}
.panel.open{ display:flex; }
/* Tabs: an icon over a word each, the open one in the accent colour. */
.tabs{ display:flex; gap:0.15rem; margin:-0.35rem -0.45rem 0; padding-bottom:0.45rem; border-bottom:1px solid var(--divider); }
.tabs button{
  flex:1 1 0; min-width:0; display:flex; flex-direction:column; align-items:center; gap:0.2rem;
  padding:0.4rem 0.1rem 0.3rem; background:none; border:none; border-radius:0.55rem;
  color:var(--text-dim); font-size:0.72rem; font-weight:600; cursor:pointer;
}
.tabs button svg{ width:1.3rem; height:1.3rem; }
.tabs button:hover{ background:var(--divider); color:var(--text); }
.tabs button[aria-selected="true"]{ color:var(--accent); background:color-mix(in srgb, var(--accent) 13%, transparent); }
.tab-body{ display:flex; flex-direction:column; gap:0.75rem; }
/* Two columns (wide, short windows): the open tab's rows flow down one column, then the next. */
.panel.open.two-col{ width:37rem; }
.panel.two-col .tab-body{ display:block; columns:2; column-gap:1.5rem; }
.panel.two-col .tab-body > *{ break-inside:avoid; margin-bottom:0.75rem; }
/* What to show: four big on/off tiles. */
.features{ display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:0.35rem; }
.features button{
  position:relative; display:flex; flex-direction:column; align-items:center; gap:0.25rem;
  padding:0.55rem 0.1rem 0.45rem; background:var(--bg); border:1px solid var(--divider); border-radius:0.6rem;
  color:var(--text-dim); font-size:0.74rem; font-weight:600; cursor:pointer;
}
.features button svg{ width:1.55rem; height:1.55rem; }
.features button:hover{ border-color:var(--text-dim); }
.features button[aria-pressed="true"]{ border-color:var(--accent2); color:var(--text); background:color-mix(in srgb, var(--accent2) 14%, var(--bg)); }
.features button[aria-pressed="true"] svg{ color:var(--accent2); }
.features button[aria-pressed="false"]{ opacity:0.6; }
.features button[aria-pressed="true"]::after{
  content:""; position:absolute; top:0.3rem; right:0.3rem; width:0.45rem; height:0.45rem;
  border-radius:50%; background:var(--accent2);
}
.hint.warn{ color:var(--accent); opacity:1; }
/* An on/off switch. */
.switch{
  position:relative; flex-shrink:0; width:2.5rem; height:1.4rem; padding:0;
  border:none; border-radius:1rem; background:var(--divider); cursor:pointer;
  transition:background-color 0.15s;
}
.switch::after{
  content:""; position:absolute; top:0.17rem; left:0.17rem; width:1.06rem; height:1.06rem;
  border-radius:50%; background:var(--text-dim); transition:transform 0.15s, background-color 0.15s;
}
.switch[aria-checked="true"]{ background:var(--accent); }
.switch[aria-checked="true"]::after{ transform:translateX(1.1rem); background:var(--bg); }
/* A tab whose part is switched off says so, with a way to turn it on. */
.off-note{
  display:flex; align-items:center; justify-content:space-between; gap:0.5rem;
  padding:0.45rem 0.6rem; border-radius:0.5rem;
  background:color-mix(in srgb, var(--accent) 12%, transparent); color:var(--text); font-size:0.8rem;
}
.off-note button, .add-btn, .test-btn{
  background:var(--bg); border:1px solid var(--divider); color:var(--text); border-radius:0.45rem;
  padding:0.3rem 0.75rem; font-size:0.8rem; font-weight:600; cursor:pointer; white-space:nowrap;
}
.off-note button:hover, .add-btn:hover, .test-btn:hover{ border-color:var(--accent2); }
.add-btn{ padding:0.5rem; border-style:dashed; }
/* Alarms: icon, time, name; then Once / Daily / Weekdays, on/off and delete. */
.alarms{ display:flex; flex-direction:column; gap:0.4rem; }
.alarms:empty{ display:none; }
.alarm{
  display:grid; grid-template-columns:2.1rem 7.8rem minmax(0, 1fr); gap:0.35rem; align-items:center;
  padding:0.4rem; border:1px solid var(--divider); border-radius:0.6rem; font-size:0.78rem;
}
.alarm.off > :not(.alarm-foot){ opacity:0.5; }
.alarm-foot{ grid-column:1 / -1; display:flex; align-items:center; gap:0.45rem; }
.alarm-foot .grow{ flex:1; }
.alarm .seg button{ padding:0.3rem 0.45rem; }
.panel .alarm input[type="time"]{ font-size:0.95rem; font-weight:700; padding:0.3rem 0.4rem; }
.alarm .tbtn.del{ font-size:1rem; }
.tbtn.del svg{ width:1.1em; height:1.1em; }
#volume{ flex:1; min-width:0; accent-color:var(--accent); }
.quiet-times{ display:flex; align-items:center; gap:0.4rem; font-size:0.8rem; }
.quiet-times input{ flex:1; }
.panel-row{ display:flex; align-items:center; justify-content:space-between; gap:0.6rem; }
.panel-col{ display:flex; flex-direction:column; align-items:stretch; gap:0.35rem; }
.dim{ opacity:0.7; }
/* Never squeezed: with overflow:hidden a shrunk group clips its last button; the label
   beside it wraps instead. */
.seg{ display:flex; flex-shrink:0; border:1px solid var(--divider); border-radius:0.5rem; overflow:hidden; }
.seg button{
  background:none; border:none; color:var(--text-dim);
  font-size:0.78rem; padding:0.3rem 0.6rem; cursor:pointer;
}
.seg button.active{ background:var(--accent); color:var(--bg); font-weight:700; }
.panel input[type="text"], .panel input[type="number"], .panel input[type="time"]{
  width:100%; min-width:0;
  background:var(--bg); border:1px solid var(--divider); color:var(--text);
  border-radius:0.4rem; padding:0.4rem 0.5rem; font-family:inherit; font-size:0.82rem;
}
.loc-list{ display:flex; flex-direction:column; gap:0.2rem; }
/* Names typed or found in Hebrew, Arabic... align to their own start (dir="auto" in app.js). */
.panel input[type="text"], .loc-list button{ text-align:start; }
.loc-list button{
  text-align:left; background:none; border:none; color:var(--text);
  font-size:0.78rem; padding:0.25rem 0.2rem; cursor:pointer; border-radius:0.3rem;
}
.loc-list button:hover{ background:var(--divider); }
.presets{ display:flex; flex-direction:column; gap:0.3rem; }
.preset{ display:grid; grid-template-columns:2.1rem 1fr 4.2rem auto; gap:0.35rem; align-items:center; font-size:0.78rem; }
.picon{
  height:100%; min-height:2rem; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:var(--bg); border:1px solid var(--divider); border-radius:0.4rem; cursor:pointer;
}
.picon[aria-expanded="true"]{ border-color:var(--accent2); }
.picon .ci{ width:1.3rem; height:1.3rem; }
/* The icon picker, opened under a preset row. */
.picker{
  display:grid; grid-template-columns:repeat(6, minmax(0, 1fr)); gap:0.3rem;
  padding:0.4rem; border:1px solid var(--divider); border-radius:0.5rem; background:var(--bg);
}
.picker button{
  height:2.1rem; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:none; border:1px solid transparent; border-radius:0.4rem;
  color:var(--text-dim); cursor:pointer;
}
.picker button:hover{ border-color:var(--divider); color:var(--text); }
.picker button.on{ border-color:var(--accent2); color:var(--accent2); background:color-mix(in srgb, var(--accent2) 14%, transparent); }
.picker button svg{ width:1.3rem; height:1.3rem; }
.picker .photo-btn{ grid-column:1 / -1; gap:0.4rem; font:inherit; font-size:0.78rem; font-weight:600; }
.picker .hint{ grid-column:1 / -1; }
.hint{ font-size:0.7rem; color:var(--text-dim); opacity:0.75; }
.panel-foot{
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:0.4rem 0.6rem;
  padding-top:0.6rem; border-top:1px solid var(--divider);
  font-size:0.7rem;
}
.panel-foot a{ color:var(--text-dim); }
.panel-foot a:hover{ color:var(--text); }
.foot-links{ display:flex; gap:0.9rem; margin-left:auto; }
.foot-links svg{ width:1.15em; height:1.15em; vertical-align:-0.25em; margin-right:0.3em; }

/* ---------- pop-up cards ----------
   Over the clock: a timer's finish or an alarm (#finish: the icon large, with its own short
   animation, its name and two buttons), a timer's card (#tcard), the keyboard shortcuts
   (#keys) and the first-start welcome (#welcome). Everything is in em of the card, which
   fitSheets in app.js sizes to the window. Each animated part's resting state is its last
   frame, so with motion off the picture is still complete. */
.sheet{
  position:fixed; inset:0; z-index:25;
  display:flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--bg) 86%, transparent);
  animation:finish-in 0.3s ease-out both;
}
.sheet-card{
  display:flex; flex-direction:column; align-items:center; gap:0.9em; flex-shrink:0;
  font-size:16px; text-align:center;
}
.sheet-art{ width:15em; height:15em; display:flex; align-items:center; justify-content:center; color:var(--accent2); }
.sheet-art svg{ width:100%; height:100%; overflow:visible; }
.sheet-title{ max-width:12em; font-size:2.3em; font-weight:700; line-height:1.1; color:var(--accent); }
.sheet-sub{ max-width:24em; font-size:1.15em; font-weight:500; line-height:1.35; color:var(--text-dim); }
.sheet-note{ font-size:0.9em; color:var(--text-dim); opacity:0.8; }
.sheet-actions{ display:flex; gap:0.75em; margin-top:0.3em; }
.sheet-actions button, .tcard-actions button{
  min-height:2.75em; padding:0 1.4em;
  border:1px solid var(--divider); border-radius:999px; background:var(--bg-panel);
  color:var(--text-dim); font:inherit; font-size:1.1em; font-weight:600; cursor:pointer; white-space:nowrap;
}
.sheet-actions button:hover, .tcard-actions button:hover{ color:var(--text); border-color:var(--text-dim); }
.sheet-actions .primary{ border-color:var(--accent); color:var(--accent); }
#finish .sheet-actions .primary{ animation:pulse 1.4s ease-in-out infinite; }
/* A timer's card: the icon big and draining, the time left, four large labelled buttons. */
.tcard-art{
  display:flex; align-items:center; justify-content:center; width:9em; height:9em;
  border-radius:50%; background:var(--bg-panel); border:1px solid var(--divider);
}
.tcard-art .ti, .tcard-art .ti-fill{ width:5.2em; height:5.2em; }
.tcard-art.paused .ti-level{ color:var(--text-dim); }
.tcard-art.done .ti-level{ color:var(--accent); }
#tcard-sub{ font-family:'Orbitron',sans-serif; font-weight:700; font-variant-numeric:tabular-nums; color:var(--accent2); }
.tcard-actions{ display:grid; grid-template-columns:1fr 1fr; gap:0.6em; margin-top:0.3em; }
.tcard-actions button{ display:flex; align-items:center; justify-content:center; gap:0.5em; color:var(--text); }
.tcard-actions button svg{ width:1.1em; height:1.1em; flex-shrink:0; }
.tcard-actions button[aria-pressed="true"]{ border-color:var(--accent2); color:var(--accent2); background:color-mix(in srgb, var(--accent2) 14%, var(--bg-panel)); }
.sheet-close{
  background:none; border:none; padding:0.3em 0.8em; cursor:pointer;
  color:var(--text-dim); font:inherit; font-size:1em; text-decoration:underline;
}
/* Keyboard shortcuts. */
.keys-list{ display:grid; grid-template-columns:auto auto; gap:0.6em 1.2em; align-items:center; margin:0.2em 0 0; font-size:1.05em; text-align:left; }
.keys-list dt{ justify-self:end; white-space:nowrap; color:var(--text-dim); }
.keys-list dd{ margin:0; white-space:nowrap; color:var(--text); }
kbd{
  display:inline-block; min-width:1.7em; padding:0.15em 0.45em;
  border:1px solid var(--divider); border-bottom-width:2px; border-radius:0.35em;
  background:var(--bg-panel); color:var(--text); font:inherit; font-weight:700; text-align:center;
}
/* First start. */
.welcome-art{ display:flex; gap:1em; color:var(--accent2); }
.welcome-art svg{ width:3em; height:3em; }
.welcome-art svg:first-child{ color:var(--accent); }
.finish-photo{ width:13em; height:13em; border-radius:50%; overflow:hidden; box-shadow:0 0 0 0.35em var(--accent2); }
.finish-photo img{ display:block; width:100%; height:100%; object-fit:cover; }
.fx-accent{ stroke:var(--accent); }
.fx-disc{ fill:var(--bg); stroke:none; }   /* keeps the dimmed clock from showing through light icons */
.fx-burst, .fx-ripple, .fx-wave{ stroke-width:3; }
.fx-burst{ opacity:0.25; transform-box:fill-box; transform-origin:center; animation:fx-burst 1.8s ease-out infinite; }
.fx-ripple{ opacity:0.5; transform-box:fill-box; transform-origin:center; animation:fx-ripple 1.8s ease-out infinite both; }
.fx-fall{ transform-box:fill-box; transform-origin:50% 100%; animation:fx-fall 1.8s cubic-bezier(0.45, 0, 0.7, 0.55) infinite; }
.fx-jump{ transform-box:fill-box; transform-origin:50% 100%; animation:fx-jump 1.1s ease-in-out infinite; }
.fx-shadow{ opacity:0.3; transform-box:fill-box; transform-origin:center; animation:fx-shadow 1.1s ease-in-out infinite; }
.fx-hit{ transform-box:fill-box; transform-origin:center; animation:fx-hit 1.9s ease-out infinite; }
.fx-arrow{ animation:fx-arrow 1.9s cubic-bezier(0.2, 0.7, 0.3, 1) infinite both; }
.fx-steam{ opacity:0.8; animation:fx-steam 2.1s ease-in-out infinite both; }
.fx-swing{ transform-box:fill-box; transform-origin:50% 8%; animation:fx-swing 1s ease-in-out infinite; }
.fx-buzz{ animation:fx-buzz 0.9s linear infinite; }
.fx-wave{ opacity:0.6; animation:fx-wave 1.2s ease-out infinite both; }
.fx-rock{ transform-box:fill-box; transform-origin:50% 60%; animation:fx-rock 2.4s ease-in-out infinite; }
.fx-twinkle{ animation:fx-twinkle 1.6s ease-in-out infinite both; }
.fx-grow{ transform-box:fill-box; transform-origin:50% 100%; animation:fx-grow 1.6s ease-out infinite; }
.fx-lift{ transform-box:fill-box; transform-origin:50% 100%; animation:fx-lift 1.2s ease-in-out infinite; }
.fx-bounce{ transform-box:fill-box; transform-origin:50% 100%; animation:fx-bounce 1s ease-in-out infinite; }
.fx-reveal{ animation:fx-reveal 2.4s cubic-bezier(0.3, 0.7, 0.3, 1) both; }
/* After the animations above, so the delay isn't reset by their shorthand. */
.fx-late{ animation-delay:0.3s; }
.fx-later{ animation-delay:0.6s; }
@keyframes finish-in{ from{ opacity:0; } to{ opacity:1; } }
@keyframes fx-burst{ 0%{ opacity:0.5; transform:scale(0.7); } 100%{ opacity:0; transform:scale(1.15); } }
@keyframes fx-ripple{ 0%,40%{ opacity:0; transform:scale(0.25); } 46%{ opacity:0.9; transform:scale(0.3); } 100%{ opacity:0; transform:scale(1.5); } }
@keyframes fx-fall{ 0%{ transform:translateY(-55%); } 42%{ transform:translateY(0) scale(1); } 52%{ transform:scale(1.18, 0.8); } 66%{ transform:scale(0.94, 1.06); } 78%,100%{ transform:scale(1); } }
@keyframes fx-jump{ 0%,100%{ transform:translateY(0) scale(1); } 12%{ transform:scale(1.06, 0.92); } 40%{ transform:translateY(-22%) rotate(-5deg); } 62%{ transform:translateY(0) rotate(0); } 74%{ transform:scale(1.05, 0.94); } }
@keyframes fx-shadow{ 0%,100%{ transform:scale(1); opacity:0.3; } 40%{ transform:scale(0.6); opacity:0.12; } }
@keyframes fx-hit{ 0%,30%,60%,100%{ transform:scale(1); } 36%{ transform:scale(0.92); } 46%{ transform:scale(1.05); } }
@keyframes fx-arrow{ 0%{ transform:translateX(-80px); opacity:0; } 8%{ opacity:1; } 32%{ transform:translateX(0); } 38%{ transform:rotate(-3deg); } 44%{ transform:rotate(2deg); } 50%,100%{ transform:none; } }
@keyframes fx-steam{ 0%{ opacity:0; transform:translateY(16px); } 35%{ opacity:0.9; } 100%{ opacity:0; transform:translateY(-30px); } }
@keyframes fx-swing{ 0%,100%{ transform:rotate(0); } 20%{ transform:rotate(14deg); } 45%{ transform:rotate(-12deg); } 70%{ transform:rotate(6deg); } }
@keyframes fx-buzz{ 0%,40%,100%{ transform:translate(0, 0); } 5%,15%,25%,35%{ transform:translate(-3px, 0) rotate(-2deg); } 10%,20%,30%{ transform:translate(3px, 0) rotate(2deg); } }
@keyframes fx-wave{ 0%{ opacity:0; } 30%{ opacity:0.8; } 100%{ opacity:0; } }
@keyframes fx-rock{ 0%,100%{ transform:rotate(-8deg); } 50%{ transform:rotate(8deg); } }
@keyframes fx-twinkle{ 0%,100%{ opacity:0.2; } 50%{ opacity:1; } }
@keyframes fx-grow{ 0%{ transform:scale(0.7, 0.5); } 55%{ transform:scale(1.04, 1.08); } 75%,100%{ transform:scale(1); } }
@keyframes fx-lift{ 0%,100%{ transform:translateY(0); } 45%,55%{ transform:translateY(-18%); } }
@keyframes fx-bounce{ 0%,100%{ transform:translateY(0) scale(1); } 15%{ transform:scale(1.08, 0.9); } 45%{ transform:translateY(-16%) scale(0.97, 1.04); } 70%{ transform:translateY(0) scale(1.04, 0.96); } }
@keyframes fx-reveal{ from{ clip-path:circle(0% at 50% 55%); } to{ clip-path:circle(75% at 50% 50%); } }

/* ---------- motion ----------
   data-motion (app.js): "full"; "calm", where nothing moves by itself (no blinking, pulsing
   or looping; a finish plays once; things still respond to the pointer); or "off", where
   nothing moves at all. Off whenever Windows has animation effects off. */
:root[data-motion="full"] .app{ transition:transform 2s ease-in-out; }   /* the screen-protection shift */
:root[data-motion="calm"] .colon .dot,
:root[data-motion="calm"] .timer.done, :root[data-motion="calm"] .timer.done .ti,
:root[data-motion="calm"] .racer.done .ti,
:root[data-motion="calm"] #finish .sheet-actions .primary{ animation:none; }
:root[data-motion="calm"] .sheet-art *{ animation-iteration-count:1 !important; }
:root[data-motion="off"] *, :root[data-motion="off"] *::before, :root[data-motion="off"] *::after{
  animation:none !important; transition:none !important;
}
