/* Tokens (color, type scale, spacing, radius, fonts, motion, z-index) come from
   /shared/porter-tokens.css, linked in <head> before this file. Castor keeps
   only documented divergences below — see apps/castor/CLAUDE.md "Divergences".

   Design language: Display serif (Fraunces) for titles/brand/hero numbers, mono
   (IBM Plex Mono) for small uppercase labels + data figures, sans (IBM Plex
   Sans) for body.

   ACCENT BLOCK (per-app). The shared token file ships no --accent (per-app
   icon-colour model — DESIGN.md). Castor's signature hues: cyan primary +
   coral second axis (2026-06 palette rebalance — work apps read cooler). Carried
   by the recoloured icon (apps/castor/icon.svg), the chrome key-accents, and the
   two chart data series. Chrome is otherwise neutral --steel.

   --velocity is kept as a NAME (the hero velocity figure references it) but no
   longer mint — it now reads in Castor's own primary hue, since the mint
   "hero colour" convention is retired and a green figure read as a good status.

   Divergence: Castor's cards use the softer 10px corner (its original design).
   Point local --radius at the shared --radius-lg so existing var(--radius) usages
   keep the 10px look without hardcoding it. */
:root{
  --radius: var(--radius-lg);

  /* Signature: cyan primary. */
  --accent:        #7fdcec;
  --accent-dim:    #2f9bb5;
  --accent-bright: #a2e8f4;
  --accent-tint:   rgba(127, 220, 236, 0.15);

  /* Hero velocity figure — Castor's own hue (mint retired). */
  --velocity:      #7fdcec;
  --velocity-dim:  #2f9bb5;
  --velocity-tint: rgba(127, 220, 236, 0.13);

  /* Second axis (rolled-in / even-PI / normalized series) — coral. Kept
     under the --accent-blue / --blue-tint names so existing usages resolve. */
  --accent-blue:    #ff8a6e;
  --accent-blue-dim:#c75a40;
  --blue-tint:      rgba(255, 138, 110, 0.14);
}
*{box-sizing:border-box;margin:0;padding:0;}
html,body{overflow-x:hidden;}
/* "Steel, not plastic": always reserve the vertical scrollbar's gutter so the
   content width never jumps when a page grows past the viewport (expanding a
   sprint, opening a modal, etc.). Without this, the scrollbar appearing on a
   tall page narrows the viewport ~15px and the whole layout reflows. */
html{scrollbar-gutter:stable;}
/* Sticky-footer flex column: the active screen grows, the footer is pushed to
   the bottom (margin-top:auto) so it's always present. The header is fixed
   (pinned) — see .app-header — and body padding-top clears it. --hdr-h is the
   header height the padding reserves; it has a mobile value in the breakpoint. */
:root{ --hdr-h: 64px; }
body{background:var(--bg);color:var(--text);font-family:var(--font-body);font-weight:300;min-height:100dvh;display:flex;flex-direction:column;padding-top:calc(var(--hdr-h) + env(safe-area-inset-top));font-size:var(--fs-base);-webkit-tap-highlight-color:transparent;}
input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0;}
input[type=number]{-moz-appearance:textfield;}
/* Placeholders read as hint text, distinctly dimmer than entered values — the
   browser default sits too close to --text. --text-dim is the placeholder token;
   opacity:1 overrides Firefox's default placeholder fade. */
input::placeholder,textarea::placeholder{color:var(--text-dim);opacity:1;}

/* ── Header ── */
/* Fixed (pinned) — position:sticky would be killed by the ancestor
   overflow-x:hidden, so the header is fixed and body reserves --hdr-h. */
.app-header{background:var(--surface);border-bottom:1px solid var(--border);padding-top:env(safe-area-inset-top);position:fixed;top:0;left:0;right:0;z-index:var(--z-sticky);}
/* Header inner shares the body content spine (--app-width) so the brand lines
   up with content and lands at the same screen-x in every app (shared header
   standard, DESIGN.md). The bar background stays full-bleed; only contents centre. */
.header-inner{max-width:var(--app-width);margin:0 auto;height:var(--hdr-h);padding:0 var(--app-pad);display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);}
/* Mini-caps serif: the chrome-header treatment (app title + section/card/modal
   headers). Uppercase Fraunces, tracked. Content titles (sprint rows, names)
   stay mixed-case — see .srow-title / .sd-name. */
.app-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-lg);letter-spacing:3px;text-transform:uppercase;color:var(--text);display:flex;align-items:center;gap:11px;min-width:0;}
/* Wordmark is a single flex child so "Castor." stays one unit (the flex gap
   doesn't split the period off). The dot just gets the accent color; a small
   negative margin cancels the last letter's trailing track so it sits tight. */
.wordmark{display:inline-block;}
/* Wordmark dot takes Castor's signature hue — the small chrome cue of identity
   beside the neutral title (shared header standard, DESIGN.md). */
.app-title .dot{color:var(--accent);margin-left:-1px;}
/* App icon: the real icon.svg, sized in em relative to the wordmark so it reads
   clearly and tracks the type-scale knob (shared header standard). */
.app-title-icon{display:block;width:1.7em;height:1.7em;flex-shrink:0;}
.back-link{font-family:var(--font-mono);font-weight:400;font-size:var(--fs-2xs);letter-spacing:.5px;color:var(--text-muted);text-decoration:none;transition:color var(--motion-base);flex-shrink:0;-webkit-tap-highlight-color:transparent;}
.back-link:hover{color:var(--steel);}
.header-divider{width:1px;height:1.2em;background:var(--border);flex-shrink:0;align-self:center;}
.nav-tabs{display:flex;gap:4px;flex-wrap:wrap;}
.nav-tab{background:none;border:none;color:var(--text-muted);font-family:var(--font-body);font-weight:400;font-size:var(--fs-sm);letter-spacing:.2px;padding:8px 13px;border-radius:var(--radius-sm);cursor:pointer;transition:all var(--motion-base);white-space:nowrap;-webkit-tap-highlight-color:transparent;}
.nav-tab.active{background:var(--accent-tint);color:var(--accent);font-weight:500;}
.nav-tab:hover:not(.active){color:var(--text);background:var(--surface-2);}

/* width:100% (not just max-width) pins the screen to the --app-width spine
   regardless of content — without it the screen is a flex item that sizes to
   its content, so the column visibly narrows when every PI/sprint is collapsed
   and widens when one expands. The intended width is always the widest state. */
.screen{display:none;width:100%;padding:24px var(--app-pad);max-width:var(--app-width);margin:0 auto;}
.screen.active{display:block;}
/* Share flag: external screenshots (e.g. for other Scrum Masters) hide the
   back-to-Porter link + its divider via a data-share attr on <body>. */
body[data-share] .back-link,body[data-share] .header-divider{display:none;}

/* Section label — mini-caps serif chrome header. */
.sl{font-family:var(--font-display);font-weight:500;font-size:var(--fs-md);letter-spacing:2.5px;text-transform:uppercase;color:var(--text);margin:26px 0 14px;}
.sl:first-child{margin-top:0;}
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:12px;}

/* ── Inputs ── */
.fl{display:flex;align-items:center;gap:5px;font-family:var(--font-mono);font-size:var(--fs-2xs);font-weight:400;letter-spacing:.6px;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px;}
.field-error{font-size:var(--fs-xs);color:var(--danger);margin-top:3px;display:none;}
input[type="text"],input[type="number"],input[type="date"],select,textarea{
  width:100%;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);
  color:var(--text);font-family:var(--font-body);font-weight:300;font-size:var(--fs-base);
  padding:8px 11px;outline:none;transition:border-color var(--motion-base);-webkit-appearance:none;appearance:none;color-scheme:dark;
}
/* Numeric/data inputs read as mono — they hold figures. */
input[type="number"],input[type="date"]{font-family:var(--font-mono);}
input:focus,select:focus,textarea:focus{border-color:var(--accent);}
input.has-error,select.has-error{border-color:var(--danger);}
select{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888ea0'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center;padding-right:28px;}
select option{background:var(--surface-2);}
textarea{resize:vertical;min-height:56px;font-family:var(--font-body);}
input[readonly]{color:var(--text-muted);cursor:default;}
.form-row{display:grid;gap:12px;}
.fr2{grid-template-columns:1fr 1fr;}
.fr3{grid-template-columns:1fr 1fr 1fr;}
.fr4{grid-template-columns:1fr 1fr 1fr 1fr;}


/* tooltip — single global floater */
.tt{position:relative;display:inline-flex;cursor:default;}
#g-tip{position:fixed;background:var(--surface-3);border:1px solid var(--border);color:var(--text-muted);font-family:var(--font-body);font-weight:300;font-size:var(--fs-xs);padding:5px 9px;border-radius:5px;pointer-events:none;z-index:var(--z-tooltip);white-space:nowrap;opacity:0;transition:opacity .12s;top:-9999px;left:-9999px;}
#g-tip.show{opacity:1;}
.tt .tip{display:none !important;}

/* badges — mono data pills */
.badge{display:inline-flex;align-items:center;justify-content:center;min-width:44px;padding:2px 7px;border-radius:var(--radius-sm);font-size:var(--fs-xs);font-weight:500;font-family:var(--font-mono);letter-spacing:0;}
.bg{background:var(--success-tint);color:var(--success);}
.br{background:var(--danger-tint);color:var(--danger);}
.bb{background:var(--blue-tint);color:var(--accent-blue);}

/* toggle */
.toggle{position:relative;width:40px;height:22px;flex-shrink:0;}
.toggle input{display:none;}
.ttrack{position:absolute;inset:0;background:var(--border);border-radius:var(--radius-pill);cursor:pointer;transition:background var(--motion-base);}
.toggle input:checked+.ttrack{background:var(--accent);}
.ttrack::after{content:'';position:absolute;left:3px;top:3px;width:16px;height:16px;border-radius:50%;background:var(--text);transition:transform var(--motion-base);}
.toggle input:checked+.ttrack::after{transform:translateX(18px);}
.trow{display:flex;align-items:center;justify-content:space-between;gap:12px;}
.tlbl{font-size:var(--fs-md);font-weight:300;color:var(--text);}

/* ── Modals ── */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.75);display:flex;align-items:center;justify-content:center;z-index:var(--z-overlay);opacity:0;pointer-events:none;transition:opacity var(--motion-base);}
.modal-overlay.open{opacity:1;pointer-events:all;}
/* The confirm dialog (#modal) can be raised FROM inside the sprint modal (e.g.
   Delete sprint). It's an interrupt, so it must sit above the other overlays —
   they share --z-overlay and would otherwise tie on DOM order, leaving the
   confirm hidden behind the sprint modal. */
#modal{z-index:calc(var(--z-overlay) + 10);}
.modal-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:420px;width:92%;transform:translateY(12px);transition:transform var(--motion-base);box-shadow:var(--shadow-modal);}
.modal-overlay.open .modal-box{transform:translateY(0);}
.modal-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-md);letter-spacing:2.5px;text-transform:uppercase;color:var(--text);margin-bottom:10px;}
.modal-msg{font-size:var(--fs-md);color:var(--text-muted);line-height:1.6;margin-bottom:20px;}
.modal-actions{display:flex;gap:8px;justify-content:flex-end;}
/* Stale-backup nag banner (#199) — full-width band under the header; inner
   content sits on the --app-width spine like the header and screens. */
.backup-nag{background:var(--warn-tint,rgba(230,176,76,.12));border-bottom:1px solid var(--border);}
.bn-inner{max-width:var(--app-width);margin:0 auto;padding:10px var(--app-pad);display:flex;align-items:center;gap:12px;}
.bn-inner::before{content:'';width:4px;align-self:stretch;background:var(--warn);border-radius:2px;flex-shrink:0;}
#bn-msg{flex:1;font-size:var(--fs-sm);color:var(--text);}
.bn-actions{display:flex;align-items:center;gap:8px;flex-shrink:0;}
/* Match the header/screen side padding on phones (the 720px block below). */
@media(max-width:720px){.bn-inner{padding:10px 14px;}}

/* First-run setup modal */
.fr-modal-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:520px;width:92%;max-height:92vh;overflow-y:auto;transform:translateY(12px);transition:transform var(--motion-base);box-shadow:var(--shadow-modal);}
.modal-overlay.open .fr-modal-box{transform:translateY(0);}
/* First-run setup roster rows */
.fr-dev{display:flex;align-items:center;gap:10px;padding:6px 2px;border-bottom:1px solid var(--border);}
.fr-dev span:first-child{flex:1;overflow:hidden;text-overflow:ellipsis;}
.fr-dev .fr-w{font-family:var(--font-mono);color:var(--text-dim);}

/* ── Sprint modal (new + edit) — decision-first gauge layout ──
   Fixed geometry: the box is a fixed max-width and the gauge's hero slot keeps
   its size whether or not history exists (empty state fills the same space),
   so nothing resizes as you type. Stacks to one column on phone, no overflow. */
.ns-modal-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:0;max-width:680px;width:96%;max-height:92vh;overflow-y:auto;overflow-x:hidden;transform:translateY(12px);transition:transform var(--motion-base);box-shadow:var(--shadow-modal);}
.modal-overlay.open .ns-modal-box{transform:translateY(0);}
.ns-header{display:flex;align-items:center;justify-content:space-between;padding:16px 22px;border-bottom:1px solid var(--border);position:sticky;top:0;background:linear-gradient(var(--surface),rgba(27,30,38,.4));z-index:10;}
.ns-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-md);letter-spacing:2.5px;text-transform:uppercase;color:var(--text);}
.ns-body{padding:20px 22px;}
.ns-footer{padding:12px 22px;border-top:1px solid var(--border);display:flex;gap:8px;justify-content:flex-end;position:sticky;bottom:0;background:var(--surface);}
.ns-col-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-xs);letter-spacing:2.5px;text-transform:uppercase;color:var(--text-muted);margin:0 0 13px;display:flex;align-items:center;gap:10px;}
.ns-col-title::after{content:"";flex:1;height:1px;background:var(--border);}
.date-warn{font-size:var(--fs-xs);color:var(--warn);margin-top:4px;display:none;}
.date-warn.show{display:block;}

/* setup form — two calm columns below the hero */
.ns-setup{display:grid;grid-template-columns:1fr 1fr;gap:24px;}

/* ── THE GAUGE — the decision hero ──
   Planned points (the commitment) set against recommended capacity, on a track
   scaled 0 → normalized velocity (the team's full-availability ceiling). */
.gauge{background:linear-gradient(160deg,var(--accent-tint),var(--velocity-tint));border:1px solid var(--accent-dim);border-radius:var(--radius);padding:20px 22px 16px;margin-bottom:22px;box-shadow:inset 0 1px 0 rgba(255,255,255,.03);}
.gauge-top{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:24px;}
.g-planned{min-width:0;}
.g-lbl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:1px;text-transform:uppercase;color:var(--text-muted);display:block;margin-bottom:3px;}
.g-big{font-family:var(--font-display);font-weight:600;font-size:var(--fs-2xl);line-height:1;color:var(--text);letter-spacing:-1px;display:block;}
.g-unit{font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--text-dim);display:block;margin-top:5px;}
.g-verdict{text-align:right;flex-shrink:0;}
.g-vrow{font-family:var(--font-display);font-weight:600;font-size:var(--fs-xl);line-height:1;color:var(--text-dim);letter-spacing:-.5px;}
.g-vsub{font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-muted);margin-top:5px;}
/* Verdict number shows the magnitude only; its COLOUR carries the direction and
   intensity. The hue + a continuous mix-toward-text are set inline by
   updateNSGauge (under = green, over = warning→danger, past-ceiling = danger),
   so the ramp scales smoothly with distance from capacity. At-capacity = steel. */
.g-verdict.at .g-vrow{color:var(--steel);}

/* Empty state — before a plan is entered, hide the bar + breakdown (they have
   nothing to plot) and drop the bottom padding so the gauge is just the prompt. */
.gauge.is-empty .gbar-wrap,.gauge.is-empty .g-bits{display:none;}
.gauge.is-empty .gauge-top{margin-bottom:0;}
.gauge.is-empty{padding-bottom:20px;}

/* the bar: neutral track + two reference marks (capacity, ceiling). The track
   carries faint zone tints only as orientation, not moral colour. */
/* Two label rows reserved above the bar so close marks (cap + velocity, which
   can even be equal) never collide horizontally: velocity rides the UPPER row
   (it's normally the larger number, so it reads higher), cap + ceiling the
   LOWER row. Each tick's stem runs from its own label row down through the bar,
   so every label is visibly connected to its mark — cap and velocity included. */
.gbar-wrap{position:relative;padding-top:36px;}
.gbar{position:relative;height:30px;border-radius:var(--radius-sm);overflow:hidden;border:1px solid var(--border);background:var(--surface-3);}
.tick{position:absolute;top:0;height:100%;width:0;pointer-events:none;}
/* default stem: from the lower label row (top:18px) down past the bar bottom. */
.tick .stem{position:absolute;top:30px;height:38px;left:0;width:2px;}
.tick .tlab{position:absolute;top:18px;left:0;transform:translateX(-50%);font-family:var(--font-mono);font-size:9px;letter-spacing:.4px;color:var(--text-muted);white-space:nowrap;}
/* velocity on the upper row — taller stem so its line reaches its higher label. */
.tick.vel .tlab{top:0;color:var(--accent-blue);}
.tick.vel .tlab b{color:var(--accent-blue);}
.tick.vel .stem{top:12px;height:56px;background:var(--accent-blue);}
/* cap merged with the ceiling (cap≈normalized velocity): right-align its label
   so it doesn't run off the end, since it now stands in for the ceiling label. */
.tick.cap.at-end .tlab{transform:translateX(-100%);}
/* faint zone bands: under-capacity vs stretch-to-ceiling. --ns-cap-pct set by JS. */
.gbar::before{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--steel-tint) 0%,var(--steel-tint) var(--ns-cap-pct,60%),var(--accent-tint) var(--ns-cap-pct,60%),var(--accent-tint) 100%);}
.pfill{position:absolute;top:0;bottom:0;left:0;border-radius:var(--radius-sm) 0 0 var(--radius-sm);background:linear-gradient(90deg,var(--accent-dim),var(--accent));box-shadow:0 0 16px rgba(127,220,236,.45);transition:width var(--motion-base),background var(--motion-base);}
.pfill.over{background:linear-gradient(90deg,var(--accent),var(--accent-bright));}
.pfill.over-ceiling{background:linear-gradient(90deg,var(--accent),var(--warn) 60%,var(--danger));}
.tick .tlab b{color:var(--text);font-weight:500;}
.tick.cap .stem{background:var(--text);}
.tick.nv .stem{background:var(--steel-dim);}
.tick.nv .tlab{color:var(--text-dim);transform:translateX(-100%);}
.gzones{display:flex;gap:16px;margin-top:9px;font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-muted);}
.gzones span{display:flex;align-items:center;gap:6px;}
.gzones i{width:18px;height:7px;border-radius:2px;}
.gzones i.zsafe{background:var(--steel-tint);}
.gzones i.zstretch{background:var(--accent-tint);}
/* capacity breakdown — fixed slot under the bar (never collapses) */
.g-bits{display:flex;flex-wrap:wrap;gap:14px;margin-top:14px;padding-top:12px;border-top:1px solid rgba(127,220,236,.2);min-height:28px;}
.g-bits .gbit{font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-muted);}
.g-bits .gbit b{color:var(--text);font-weight:500;}
.g-bits .gbit-empty{font-size:var(--fs-2xs);color:var(--text-dim);}

/* availability — slider rows showing each dev's weight */
.ns-avail{display:flex;flex-direction:column;gap:11px;}
.ns-av{display:grid;grid-template-columns:88px 1fr 42px;align-items:center;gap:12px;}
.ns-av-name{font-size:var(--fs-md);color:var(--text);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.ns-av input[type=range]{width:100%;accent-color:var(--accent);cursor:pointer;}
.ns-av input[type=range]:disabled{accent-color:var(--steel-dim);cursor:not-allowed;}
.ns-av-v{font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--text);text-align:right;}
/* capacity modifier slider — sits under the roster, same visual language */
.ns-mod{margin-top:16px;padding-top:14px;border-top:1px solid var(--border);}
.ns-mod-row{display:grid;grid-template-columns:1fr 42px;align-items:center;gap:12px;}
.ns-mod-row input[type=range]{width:100%;accent-color:var(--accent);cursor:pointer;}
.ns-mod-v{font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--text);text-align:right;}

/* ── Sprints ── */
.sprints-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
.pi-group{margin-bottom:10px;border-radius:var(--radius);border:1px solid var(--border);overflow:hidden;}
.pi-hdr{display:flex;align-items:center;justify-content:space-between;padding:13px 16px;background:var(--surface);cursor:pointer;transition:background var(--motion-fast);user-select:none;}
.pi-hdr:hover{background:var(--surface-2);}
.pi-hdr-left{display:flex;align-items:center;gap:14px;}
.pi-lbl{font-family:var(--font-mono);font-weight:500;font-size:var(--fs-base);letter-spacing:.3px;color:var(--accent);min-width:62px;}
.pi-icon-stats{display:flex;align-items:center;gap:14px;font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--text-muted);}
/* PI-group header stat chips. Shared with the (former) sprint-row right side,
   which moved to .srow-read/.m; these fixed-width mono chips stay for the PI
   summary header (Completed/Planned, over-under badge, avg confidence). */
.istat{display:flex;align-items:center;gap:5px;font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--text-muted);white-space:nowrap;width:88px;justify-content:flex-end;}
.istat.w52{width:58px;}.istat.w96{width:112px;}.istat.w44{width:50px;}
.istat strong{color:var(--text);font-weight:500;}
.pi-chevron{color:var(--text-dim);font-size:var(--fs-xs);transition:transform var(--motion-base);flex-shrink:0;}
.pi-hdr.open .pi-chevron{transform:rotate(180deg);}
.pi-body{display:none;border-top:1px solid var(--border);overflow:visible;}
.pi-body.open{display:block;}

/* ── sprint row ──
   Stable grid that never reflows by lifecycle state: identity | progress bar |
   six-cell readout. The progress bar IS the status indicator (no chip). The bar
   column flexes (1fr) to absorb the row width so the readout's fixed cells stay
   put — no reflow when sprints/PIs collapse or expand. */
.srow{border-bottom:1px solid var(--border);background:var(--surface);cursor:pointer;transition:background var(--motion-fast);}
.srow:last-child{border-bottom:none;}
.srow:hover{background:var(--surface-2);}
.srow.expanded{background:var(--surface-2);box-shadow:inset 3px 0 0 var(--accent);}
.srow-top{display:grid;grid-template-columns:165px 1fr auto;align-items:center;padding:13px 16px;gap:22px;}
.srow-id{display:flex;flex-direction:column;gap:3px;min-width:0;}
.srow-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-md);letter-spacing:0;color:var(--text);}
.srow-dates{font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--text-dim);}
.srow-bar{display:flex;flex-direction:column;gap:5px;min-width:0;}
.srow-track{position:relative;height:6px;border-radius:3px;background:var(--surface-3);overflow:hidden;}
.srow-fill{position:absolute;inset:0 auto 0 0;border-radius:3px;background:var(--accent);}
.srow-status{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.4px;text-transform:uppercase;color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* per-phase bar + label colour */
.lc-complete .srow-fill{background:var(--success);} .lc-complete .srow-status{color:var(--success);}
.lc-active .srow-fill{background:var(--accent);} .lc-active .srow-status{color:var(--accent-bright);}
.lc-awaiting .srow-fill{background:var(--warn);} .lc-awaiting .srow-status{color:var(--warn);}
.lc-upcoming .srow-track{background:transparent;border:1px dashed var(--border);} .lc-upcoming .srow-status{color:var(--text-dim);}
/* six-cell readout — fixed widths so columns never shift between states */
.srow-read{display:grid;grid-template-columns:repeat(6,72px);align-items:center;}
.srow-read .m{height:40px;justify-content:center;border-left:1px solid var(--border);padding:0 4px;}
.srow-read .m:first-child{border-left:none;}
.m{display:flex;flex-direction:column;align-items:center;font-family:var(--font-mono);line-height:1.2;}
.m .mv{font-size:var(--fs-md);color:var(--text);font-weight:500;white-space:nowrap;}
.m .mv.dim{color:var(--text-dim);font-weight:400;}
.m .mv-suf{color:var(--text-dim);font-weight:400;font-size:var(--fs-sm);margin-left:1px;}
.m .ml{font-size:var(--fs-2xs);letter-spacing:.4px;text-transform:uppercase;color:var(--text-dim);margin-top:2px;}

/* ── detail / expanded ── */
.srow-detail{display:none;border-top:1px solid var(--border);padding:14px 16px 0;cursor:default;}
.srow-detail.open{display:block;}
.detail-sec{margin-top:14px;padding-bottom:14px;}
.detail-sec:first-child{margin-top:0;}
.detail-sec-hdr{display:flex;align-items:center;justify-content:space-between;font-family:var(--font-mono);font-size:var(--fs-xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-muted);padding-bottom:6px;border-bottom:1px solid var(--border);margin-bottom:10px;min-height:28px;}
.detail-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
.detail-stat{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;}
.dsv{font-family:var(--font-mono);font-weight:500;font-size:var(--fs-lg);color:var(--accent);}
.dsl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.6px;text-transform:uppercase;color:var(--text-dim);margin-top:2px;}

/* expanded closeout: hero band */
.exp-hero{display:flex;margin-bottom:14px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface-2);}
.exp-hero .cell{flex:1;padding:14px 16px;border-right:1px solid var(--border);}
.exp-hero .cell:last-child{border-right:none;}
.exp-hero .hv{font-family:var(--font-display);font-weight:500;font-size:1.7rem;color:var(--text);line-height:1;}
.exp-hero .hv.pos{color:var(--success);} .exp-hero .hv.neg{color:var(--danger);} .exp-hero .hv.accent{color:var(--accent);}
.exp-hero .hl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.7px;text-transform:uppercase;color:var(--text-dim);margin-top:7px;}
.exp-hero .hsub{font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--text-muted);margin-top:3px;}

/* Readonly closeout: rolled cards (left, stacked OUT then IN) beside the sprint
   notes (right) — half width each, instead of the rolled cards spanning full
   width with notes stacked below. */
.closeout-cols{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start;}
.closeout-rolled{display:flex;flex-direction:column;gap:12px;}
.closeout-cols .notes-sec{margin-top:0;}
.rcard{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;}
.rcard-hd{display:flex;align-items:center;gap:8px;margin-bottom:6px;}
.rcard-hd .roll-nm{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:1px;text-transform:uppercase;}
.rcard-hd .roll-nm.lc-in{color:var(--accent-blue);} .rcard-hd .roll-nm.lc-out{color:var(--danger);}
.rcard-hd .roll-cnt{margin-left:auto;font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--text-dim);}
.rempty{color:var(--text-dim);font-size:var(--fs-sm);font-style:italic;padding:4px 2px;}
/* Rolled-issue PILLS (shared by read + edit). Each issue is a self-contained
   pill carrying its own points, so there are no shared columns to align — what
   broke every prior table/grid version. Each pill is FULL-WIDTH, one per line
   (predictable sizing, fits the app's narrow cards): swatch + issue number take
   the flex space on the left; points and the trailing control are pinned right. */
.pill-flow{display:flex;flex-direction:column;gap:8px;}
.pill{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 13px;border-radius:var(--radius-pill);border:1px solid var(--border);background:var(--surface-3);font-family:var(--font-mono);font-size:var(--fs-md);}
.pill .sw{width:9px;height:9px;border-radius:3px;flex-shrink:0;}
.pill.lc-in .sw{background:var(--accent-blue);}
.pill.lc-out .sw{background:var(--danger);}
.pill .p-num{color:var(--text);font-weight:500;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.pill .p-num::before{content:"#";color:var(--text-dim);margin-right:3px;}
.pill .p-pts{font-weight:500;margin-left:auto;flex-shrink:0;}
.pill.lc-in .p-pts{color:var(--accent-blue);}
.pill.lc-out .p-pts{color:var(--danger);}
.pill .p-act{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;color:var(--text-dim);text-decoration:none;cursor:pointer;flex-shrink:0;transition:background var(--motion-fast),color var(--motion-fast);}
.pill .p-act:hover{background:var(--surface);color:var(--text);}
.pill .p-act.x:hover{color:var(--danger);}
.pill .p-act.go:hover{color:var(--accent);}
/* add pill — same full-width shape, dashed; issue input flexes, pts + ✓ pinned right */
.pill-add{display:flex;align-items:center;gap:8px;width:100%;padding:6px 6px 6px 13px;border-radius:var(--radius-pill);border:1px dashed var(--accent-dim);background:transparent;font-family:var(--font-mono);font-size:var(--fs-md);}
.pill-add:focus-within{border-style:solid;border-color:var(--accent);}
.pill-add input{border:none;background:transparent;color:var(--text);font-family:var(--font-mono);font-size:var(--fs-md);font-weight:500;padding:2px 0;}
.pill-add input:focus{outline:none;}
.pill-add input::placeholder{color:var(--text-dim);font-weight:400;}
.pill-add .pa-num{flex:1;min-width:0;}
.pill-add .pa-pts{width:34px;text-align:right;margin-left:auto;flex-shrink:0;}
.pill-add .pa-go{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;border:none;background:var(--accent-tint);color:var(--accent-bright);cursor:pointer;flex-shrink:0;transition:background var(--motion-fast),color var(--motion-fast);}
.pill-add .pa-go:hover{background:var(--accent);color:#0b0d10;}

/* sprint notes */
.notes-sec{margin-top:14px;}
.notes-hd{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:1.1px;text-transform:uppercase;color:var(--text-muted);margin-bottom:9px;}
.notes-box{padding:11px 13px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--fs-sm);color:var(--text-muted);line-height:1.6;white-space:pre-line;}
.notes-box.empty{color:var(--text-dim);font-style:italic;}
.detail-actions{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 0 14px;border-top:1px solid var(--border);min-height:52px;}
.detail-actions .action-group{display:flex;align-items:center;gap:8px;margin-left:auto;}
.detail-actions .action-group-left{display:flex;align-items:center;gap:8px;}

/* inline forms */
.inner-form{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:14px;margin-top:10px;}

/* closeout layout */
.co-layout{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
/* edit-state rolled cards: two cards side by side */
.ed-two{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.ed-card{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;}
.ed-err{font-family:var(--font-body);font-size:var(--fs-2xs);color:var(--danger);min-height:14px;margin-top:8px;}
.co-stats{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px;}
.co-stat{background:var(--surface-3);border:1px solid var(--accent-dim);border-radius:var(--radius-sm);padding:10px 14px;text-align:center;}
.co-stat-lbl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-dim);margin-bottom:4px;}
.co-stat-val{font-family:var(--font-mono);font-weight:500;font-size:var(--fs-lg);color:var(--text);}
.has-error{border-color:var(--danger) !important;}
.err-tip{position:absolute;left:0;bottom:calc(100% + 4px);background:var(--danger);color:#fff;font-size:var(--fs-2xs);padding:4px 8px;border-radius:4px;white-space:nowrap;pointer-events:none;z-index:50;display:none;}
.err-tip.show{display:block;}
.inp-wrap{position:relative;}

/* ── Standup — three-phase runner (Setup → Run → Output) ──
   Phases swap in place; each owns the full width. The step header tracks
   progress. Replaces the old two-column setup/runner split. */
.sd-steps{display:flex;align-items:center;gap:0;margin-bottom:22px;}
.sd-step{display:flex;align-items:center;gap:9px;font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-dim);}
.sd-step .num{width:22px;height:22px;border-radius:50%;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:var(--fs-2xs);transition:all var(--motion-base);}
.sd-step.on{color:var(--text);}
.sd-step.on .num{background:var(--accent);border-color:var(--accent);color:var(--bg);}
.sd-step.done{color:var(--text-muted);}
.sd-step.done .num{border-color:var(--accent-dim);color:var(--accent);}
.sd-step-line{flex:1;height:1px;background:var(--border);margin:0 14px;min-width:24px;}
.sd-phase{display:none;}
.sd-phase.show{display:block;}
.sd-setup-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.sd-setup-grid .full{grid-column:1/-1;}
.sd-setup-grid textarea{min-height:90px;overflow:hidden;resize:none;}
.sd-actions{display:flex;gap:10px;margin-top:20px;align-items:center;}
.sd-spacer{flex:1;}
/* Page-direction arrows: trailing for forward, leading (sd-ar-l) for back. */
.sd-ar{width:14px;height:14px;}
.btn .sd-ar-l{margin-right:0;}
/* Run phase: hero active speaker + a "round order" rail. */
.sd-runhead{display:flex;align-items:baseline;gap:12px;margin-bottom:16px;}
.sd-runctx{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.6px;text-transform:uppercase;color:var(--text-dim);}
.sd-run-wrap{display:grid;grid-template-columns:1fr 248px;gap:18px;align-items:start;}
.sd-active{background:var(--surface);border:1px solid var(--accent);border-radius:var(--radius);padding:22px 24px;box-shadow:0 0 0 4px var(--accent-tint);}
.sd-who{display:flex;align-items:baseline;gap:12px;margin-bottom:2px;}
.sd-who h3{font-family:var(--font-display);font-weight:500;font-size:var(--fs-xl);letter-spacing:0;color:var(--accent);}
.sd-who .sd-tag{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.6px;text-transform:uppercase;color:var(--text-dim);}
.sd-who .sd-pos{margin-left:auto;font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-dim);letter-spacing:.6px;}
.sd-active textarea{min-height:120px;margin-top:14px;overflow:hidden;resize:none;font-size:var(--fs-base);}
.sd-nav{display:flex;gap:10px;margin-top:14px;align-items:center;}
.sd-nav .kb{font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-dim);margin-left:auto;}
.sd-nav .kb kbd{background:var(--surface-3);border:1px solid var(--border);border-radius:4px;padding:1px 6px;color:var(--text-muted);font-size:var(--fs-2xs);}
.sd-rail-head{display:flex;align-items:center;gap:10px;margin-bottom:10px;}
.sd-rail-lbl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-dim);}
/* Progress pill: counts VISITED (blank-but-visited counts; NIA is legit). */
.sd-prog{margin-left:auto;font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-muted);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-pill);padding:2px 9px;transition:all var(--motion-base);}
.sd-prog.complete{color:var(--success);border-color:rgba(92,184,138,.4);background:rgba(92,184,138,.1);}
.sd-rail-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--radius-sm);font-size:var(--fs-md);color:var(--text-muted);transition:all var(--motion-base);cursor:pointer;margin-bottom:4px;}
.sd-rail-item:hover{background:var(--surface-2);}
.sd-rail-item.visited{color:var(--text-dim);}
.sd-rail-item.now{background:var(--accent-tint);color:var(--text);border:1px solid var(--accent-dim);}
.sd-rail-item .ic{width:16px;height:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center;}
.sd-rail-item .ic svg{width:15px;height:15px;}
.sd-rail-item .ic .dot{width:6px;height:6px;border-radius:50%;background:var(--text-dim);}
.sd-rail-item .gt{font-size:var(--fs-2xs);color:var(--text-dim);margin-left:auto;}
/* Output blocks: Copy is a header action (fixed position, not floating). */
.out-block{margin-bottom:18px;}
.out-block:last-child{margin-bottom:0;}
.out-head{display:flex;align-items:center;gap:12px;margin-bottom:8px;}

/* ── Metrics ── */
.chart-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px;margin-bottom:16px;}
.chart-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:160px;color:var(--text-dim);font-size:var(--fs-sm);gap:8px;}
/* Chart sizing: the wrap is a fixed-height box and Chart.js fills it
   (maintainAspectRatio:false). DON'T force canvas width with !important — that
   fought Chart.js's own sizing and produced the stretched/distorted charts. */
.chart-wrap{position:relative;width:100%;height:300px;}
.chart-wrap canvas{display:block;}
.pi-sum-table{width:100%;border-collapse:collapse;}
.pi-sum-table th{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-muted);text-align:right;padding:8px 10px;border-bottom:1px solid var(--border);}
.pi-sum-table th:first-child{text-align:left;}
.pi-sum-table td{font-family:var(--font-mono);padding:10px;font-size:var(--fs-md);text-align:right;border-bottom:1px solid var(--border);}
.pi-sum-table td:first-child{text-align:left;color:var(--accent);letter-spacing:.3px;}
.pi-sum-table tr:last-child td{border-bottom:none;}

/* standup output */
.out-lbl{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.8px;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px;}
.sd-output{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:14px;font-size:var(--fs-md);line-height:1.9;white-space:pre-wrap;word-break:break-word;min-height:60px;color:var(--text-muted);font-family:var(--font-mono);}
.url-output{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:11px 13px;font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--text-dim);word-break:break-all;line-height:1.6;}
/* Copy sits in the block header — fixed 92px so "✓ Copied" never crowds and
   the width stays consistent between the two blocks. */
.copy-btn{margin-left:auto;background:none;border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-muted);padding:6px 0;font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.4px;text-transform:uppercase;cursor:pointer;transition:all var(--motion-base);white-space:nowrap;flex-shrink:0;width:92px;text-align:center;-webkit-tap-highlight-color:transparent;}
.copy-btn:hover{border-color:var(--accent);color:var(--accent);}
.copy-btn.copied{border-color:var(--success);color:var(--success);}

/* ── Settings ──
   Grouped by concern down one spine: Roster + Forecasting side-by-side, then
   Integrations (URLs full-width), then Data. A persistent top save zone with
   true DRAFT-vs-SAVED dirty-tracking replaces the old sticky bottom bar. */
.set-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:22px;flex-wrap:wrap;}
.set-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-xl);letter-spacing:0;color:var(--text);}
.set-savezone{display:flex;align-items:center;gap:12px;}
.set-savestate{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.6px;text-transform:uppercase;transition:color var(--motion-base);}
.set-savestate.clean{color:var(--text-dim);}
.set-savestate.dirty{color:var(--warn);}
.set-savestate .dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:6px;vertical-align:middle;background:var(--text-dim);transition:background var(--motion-base);}
.set-savestate.dirty .dot{background:var(--warn);}
.set-grid{display:grid;grid-template-columns:1.55fr 1fr;gap:16px;align-items:start;}
.data-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;}
.data-spacer{flex:1;}
.sc{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:12px;}
.sc-hdr{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;gap:8px;flex-wrap:wrap;}
.sc-title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-md);letter-spacing:2.5px;text-transform:uppercase;color:var(--text);}
/* Roster as a table: name (+ You pill) · weight stepper · remove. */
.roster-tab{width:100%;border-collapse:collapse;}
.roster-tab td{padding:9px 0;border-bottom:1px solid var(--border);vertical-align:middle;}
.roster-tab tr:last-child td{border-bottom:none;}
.dev-roster-name{font-size:var(--fs-md);font-weight:400;color:var(--text);}
.dev-roster-name .youtag{margin-left:8px;font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.4px;text-transform:uppercase;color:var(--success);border:1px solid rgba(92,184,138,.35);border-radius:var(--radius-pill);padding:1px 7px;}
.roster-tab .wt-cell{text-align:center;width:1%;white-space:nowrap;}
.roster-tab .rm-cell{text-align:right;width:1%;}
/* Weight stepper: −/+ around a static centered value (no free-type). Pending
   value shows in --warn until Save. Clamp 0.1–3.0; ends disabled at bounds. */
.wt-stepper{display:inline-flex;align-items:center;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;background:var(--surface-2);}
.wt-step{width:28px;height:32px;flex-shrink:0;border:none;background:var(--surface-2);color:var(--text-muted);cursor:pointer;font-size:16px;line-height:1;transition:all var(--motion-fast);-webkit-tap-highlight-color:transparent;}
.wt-step:hover:not(:disabled){background:var(--surface-3);color:var(--text);}
.wt-step:disabled{opacity:.3;cursor:default;}
.wt-val{width:42px;text-align:center;font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--text);border-left:1px solid var(--border);border-right:1px solid var(--border);line-height:32px;}
.wt-val.changed{color:var(--warn);}
/* Quiet self-dev selector under the roster (one team-wide value, edited rarely). */
.self-line{display:flex;align-items:center;gap:8px;margin-top:14px;font-size:var(--fs-xs);color:var(--text-dim);}
.self-line .lab{font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.6px;text-transform:uppercase;}
.self-line select{width:auto;background:none;border:none;color:var(--text-muted);font-size:var(--fs-xs);padding:2px 4px;border-radius:var(--radius-sm);cursor:pointer;transition:all var(--motion-base);}
.self-line select:hover{background:var(--surface-2);color:var(--text);}
.add-dev-form{display:none;margin-top:10px;padding-top:10px;border-top:1px solid var(--border);}
.add-dev-form.open{display:block;}
.pi-ci{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border);font-size:var(--fs-md);color:var(--text-muted);cursor:pointer;}
.pi-ci:last-child{border-bottom:none;}
.pi-ci input{width:15px;height:15px;accent-color:var(--accent);flex-shrink:0;}
.export-modal-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:460px;width:92%;transform:translateY(12px);transition:transform var(--motion-base);box-shadow:var(--shadow-modal);}
.modal-overlay.open .export-modal-box{transform:translateY(0);}

/* ── Buttons ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:9px 15px;border-radius:var(--radius-sm);border:none;cursor:pointer;font-family:var(--font-body);font-weight:500;font-size:var(--fs-sm);letter-spacing:0;transition:all var(--motion-base);white-space:nowrap;-webkit-tap-highlight-color:transparent;}
.bp{background:var(--accent);color:var(--bg);}.bp:hover{background:var(--accent-bright);}
.bs{background:none;border:1px solid var(--border);color:var(--text-muted);}.bs:hover{border-color:var(--accent);color:var(--text);}
.bsuc{background:var(--success);color:#fff;}.bsuc:hover{filter:brightness(1.12);}
.bd{background:none;border:1px solid var(--danger);color:var(--danger);}.bd:hover{background:var(--danger-tint);}
.bwarn{background:none;border:1px solid var(--warn);color:var(--warn);}.bwarn:hover{background:var(--warn-tint);}
.bsm{padding:6px 11px;font-size:var(--fs-xs);}
.ib{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--radius-sm);border:1px solid var(--border);background:none;color:var(--text-muted);cursor:pointer;transition:all var(--motion-base);font-size:14px;flex-shrink:0;-webkit-tap-highlight-color:transparent;}
.ib:hover{border-color:var(--accent);color:var(--accent);}
.ib.idanger:hover{border-color:var(--danger);color:var(--danger);}
.ib.iwarn:hover{border-color:var(--warn);color:var(--warn);}
.ib.isuc:hover{border-color:var(--success);color:var(--success);}

/* toast */
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(80px);border-radius:var(--radius-sm);padding:10px 20px;font-size:var(--fs-sm);font-family:var(--font-mono);letter-spacing:.3px;transition:transform 0.3s ease;z-index:var(--z-toast);white-space:nowrap;background:var(--surface-3);border:1px solid var(--accent);color:var(--accent);}
.toast.show{transform:translateX(-50%) translateY(0);}
.toast.terror{background:var(--danger-tint);border-color:var(--danger);color:var(--danger);}
.toast.tok{background:var(--success-tint);border-color:var(--success);color:var(--success);}
.empty-state{text-align:center;color:var(--text-dim);font-size:var(--fs-md);padding:40px 20px;}
/* Footer: always present (margin-top:auto pins it to the bottom of the flex
   column when content is short). Quiet credit + version stamp. */
.app-footer{margin-top:auto;text-align:center;font-family:var(--font-mono);font-size:var(--fs-2xs);letter-spacing:.4px;color:var(--text-dim);opacity:0.7;padding:24px 16px calc(24px + env(safe-area-inset-bottom));border-top:1px solid var(--border);}
.app-footer .sep{opacity:0.5;margin:0 7px;}

.lock-badge{display:inline-flex;align-items:center;gap:4px;font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--text-dim);text-transform:none;letter-spacing:0;}

@media(max-width:820px){.set-grid{grid-template-columns:1fr;}}
@media(max-width:720px){
  /* Mobile size knob: smaller base so the desktop 18px scale doesn't dominate
     phones. Whole app scales from this the same way as the desktop knob. */
  html{font-size:15px;}
  /* Phone header wraps to two rows (identity + tabs) → reserve more height. */
  :root{ --hdr-h: 98px; }
  /* Sprint modal on phone: setup collapses to one column and the gauge hero
     stacks (planned number above the verdict) so nothing crowds or overflows. */
  .ns-setup{grid-template-columns:1fr;gap:18px;}
  .gauge-top{flex-direction:column;align-items:flex-start;gap:10px;}
  .g-verdict{text-align:left;}
  .set-grid{grid-template-columns:1fr;}
  .set-head{align-items:flex-start;}
  .sd-run-wrap{grid-template-columns:1fr;}
  .sd-setup-grid{grid-template-columns:1fr;}
  .detail-grid{grid-template-columns:1fr 1fr;}
  .fr4{grid-template-columns:1fr 1fr;}
  .co-layout{grid-template-columns:1fr;}
  .closeout-cols{grid-template-columns:1fr;}
  .ed-two{grid-template-columns:1fr;}
  .exp-hero{flex-wrap:wrap;}
  .exp-hero .cell{flex:1 1 50%;border-right:1px solid var(--border);border-bottom:1px solid var(--border);}
  .screen{padding:18px 14px;}
  /* Phone header: the inner spine stacks into two rows — identity row
     (back · icon · title), then a full-width tab row that scrolls horizontally
     if the four tabs don't fit, so the wider mini-caps title never collides
     with the tabs. Height grows with content (reset the desktop fixed height);
     body still reserves --hdr-h (98px) for it. */
  .header-inner{flex-wrap:wrap;gap:8px 0;height:auto;padding:12px 14px;}
  .app-header{padding-top:env(safe-area-inset-top);}
  .app-title{font-size:var(--fs-lg);letter-spacing:2px;flex:1 1 100%;min-width:0;}
  .nav-tabs{flex:1 1 100%;gap:4px;overflow-x:auto;-webkit-overflow-scrolling:touch;flex-wrap:nowrap;scrollbar-width:none;}
  .nav-tabs::-webkit-scrollbar{display:none;}
  .nav-tab{padding:7px 12px;flex-shrink:0;}
  /* Sprint row on phone: the three grid columns stack into rows — identity,
     then the progress bar full-width, then the readout. Six cells wrap to a
     3-up two-row grid so they fit a phone without horizontal scroll. */
  .srow-top{grid-template-columns:1fr;gap:12px;}
  .srow-bar{width:100%;}
  .srow-read{grid-template-columns:repeat(3,1fr);width:100%;row-gap:12px;}
  .srow-read .m{padding:0 2px;}
  /* drop the left divider on the first cell of each wrapped row (cols 1 and 4) */
  .srow-read .m:nth-child(3n+1){border-left:none;}
  /* Overflow backstops: nothing should push past the viewport on phone. */
  .pi-hdr{flex-wrap:wrap;gap:8px;}
  .pi-icon-stats{flex-wrap:wrap;gap:8px 12px;}
  .sc,.card,.chart-card{min-width:0;}
}
