:root{
  /* Lighter, cleaner sky-blue - closer to Kumon's own brand blue than the
     previous deeper cyan, which read as noticeably darker/more saturated
     by comparison. */
  --bg:#5DBCE3; --surface:#f4fafd; --surface-2:#e1f0f8;
  --ink:#0e2738; --ink-soft:#23516c; --ink-faint:#2c5470;
  --rule:#bfe0ee; --accent:#0088C4; --accent-ink:#0a6088; --accent-soft:#d9f0fa;
  --present:#0088C4; --departed:#4c7891; --departed-soft:#dceaf2;
  --error:#b6473c; --error-soft:#f6ddd9;
  --success:#2f7d52;
  /* Time Clock mode's own accent - a muted dusty plum, far enough from the
     app's cyan-blue on the color wheel to read as clearly different without
     competing with it the way an earlier, more saturated amber did (that
     version doubled down by also painting the whole page that color, which
     read as loud rather than considered). Used as an accent only now, the
     same restrained way the marketing site uses its own blue: small UI
     (buttons, active tabs, badges) against a light neutral page, never a
     full-bleed field. */
  --tc-accent:#6d5a8c; --tc-accent-ink:#493c5e; --tc-accent-soft:#ece6f2;
  --shadow: 0 1px 2px rgba(10,40,60,.14), 0 8px 24px rgba(10,40,60,.12);
}
/* Time Clock mode - same custom-property override mechanism as before
   (--bg/--accent/--accent-ink/--accent-soft, read by every rule that uses
   them, rather than duplicating each one). Scoped to body.staff-mode, not a
   child of body, because custom properties only cascade to descendants -
   body's own `background:var(--bg)` has to see the override on body itself.
   --bg now resolves to --surface-2 (a light blue-gray, not a saturated
   color) - the marketing site's own "light page, cards stand out via their
   own white-ish fill + border + shadow" approach, reused here instead of
   inventing a second one. */
body.staff-mode{
  --bg:var(--surface-2); --accent:var(--tc-accent); --accent-ink:var(--tc-accent-ink); --accent-soft:var(--tc-accent-soft);
}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;height:100%;}
body{
  background:var(--bg); color:var(--ink);
  font-family:"Avenir Next","Avenir Next LT Pro",Avenir,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  font-size:16px; line-height:1.5; font-weight:400;
}
h1,h2{font-weight:500; margin:0;}

/* Kiosk — friendlier, rounder font than the rest of the site, since this is
   the screen students actually type on. */
.kiosk-page{
  max-width:680px; margin:0 auto; padding:32px 20px 60px; min-height:100%;
  display:flex; flex-direction:column;
  font-family:"Nunito","Avenir Next",-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
.kiosk-page h1{font-size:3.2rem; text-align:center; margin-bottom:4px;}
.kiosk-subtitle{font-size:2.24rem; text-align:center; color:var(--ink-soft); font-weight:500; margin:0 0 32px;}
.kiosk-header{
  position:fixed; top:0; left:0; right:0; z-index:10;
  display:flex; justify-content:space-between; align-items:center;
  padding:16px 20px;
}
.kiosk-main{flex:1; display:flex; flex-direction:column; justify-content:center;}
.kiosk-header-left{display:flex; align-items:center; gap:10px;}
/* Actions on top, identity underneath - same stacked pattern as
   .dash-header-right/.dash-header-actions, so the kiosk header reads
   consistently with every other page's header rather than its own
   one-off layout. */
.kiosk-header-right{display:flex; flex-direction:column; align-items:flex-end; gap:6px;}
.kiosk-header-actions{display:flex; align-items:center; gap:8px; flex-wrap:wrap; justify-content:flex-end;}
.kiosk-logo{display:block; height:24px; width:auto;}
/* Highlighted (not the faint gray used elsewhere) - this is the one piece
   of header text that actually matters to whoever's standing at the kiosk:
   confirmation of which account unlocked it. */
.kiosk-user{font-size:.8rem; color:var(--accent-ink); font-weight:700;}
#search-input{
  width:100%; padding:32px 36px; font-size:2.4rem; border-radius:16px;
  border:1px solid var(--rule); background:var(--surface); color:var(--ink);
  box-shadow:var(--shadow); text-align:center;
}
#search-input:focus{outline:2px solid var(--accent);}
ul.plain-list{list-style:none; margin:20px 0 0; padding:0;}
.result{
  display:flex; justify-content:space-between; align-items:center;
  padding:32px 36px; margin-bottom:12px; border-radius:14px;
  background:var(--surface); border:1px solid var(--rule); box-shadow:var(--shadow);
  font-size:2.1rem; cursor:pointer;
}
.result{transition:background-color .12s ease, transform .08s ease;}
.result:hover{background:var(--surface-2);}
.result:active{background:var(--surface-2); transform:scale(0.99);}
.pill{display:inline-block; font-size:.78rem; font-weight:600; padding:3px 10px; border-radius:999px;}
.pill.present{background:var(--accent-soft); color:var(--accent-ink);}
.pill.departed{background:var(--departed-soft); color:var(--departed);}
.kiosk-page .pill{font-size:1.1rem; padding:6px 16px;}

/* Generic "this row is deactivated" treatment - used by both the Owner
   Overview centers table and the Staff Roster table. */
tr.row-inactive{filter:grayscale(1); opacity:.55;}

#confirm, #checkout-who{
  margin-top:32px; padding:40px 32px; border-radius:18px; background:var(--surface);
  border:1px solid var(--rule); box-shadow:var(--shadow); text-align:center;
}
#confirm h2, #checkout-who h2{font-size:2.8rem; margin-bottom:28px;}
#checkout-who .kiosk-subtitle{margin-top:0; margin-bottom:20px;}
#checkout-who input{font-size:1.4rem; padding:16px 20px;}
.card textarea{width:100%;}
.btn-checkout{
  font-size:1.3rem; font-weight:600; padding:16px 24px; border-radius:12px;
  border:none; cursor:pointer; width:100%; margin-bottom:10px; text-align:center;
  transition:filter .12s ease, transform .08s ease, background-color .15s ease, opacity .15s ease;
}
.btn-checkout:hover{filter:brightness(1.08);}
.btn{
  font-size:2.2rem; font-weight:600; padding:28px 40px; border-radius:14px;
  border:none; cursor:pointer; width:100%; margin-bottom:12px; text-align:center;
  transition:filter .12s ease, transform .08s ease, background-color .15s ease, opacity .15s ease;
}
.btn-primary{background:var(--accent); color:#fff;}
.btn-secondary{background:var(--surface-2); color:var(--ink-soft); border:1px solid var(--rule);}

.status{
  position:fixed; bottom:24px; left:50%; transform:translateX(-50%);
  padding:24px 36px; border-radius:14px; font-weight:600; font-size:1.6rem; box-shadow:var(--shadow);
  max-width:90%; text-align:center;
}
.status.success{background:var(--accent-soft); color:var(--accent-ink);}
.status.error{background:var(--error-soft); color:var(--error);}
.status[hidden]{display:none;}

#offline-banner{
  background:var(--error-soft); color:var(--error); text-align:center;
  padding:16px; font-size:1.7rem; font-weight:600; border-radius:8px; margin-bottom:16px;
}
#offline-banner[hidden]{display:none;}

/* Dashboard */
.dash-page{max-width:1000px; margin:0 auto; padding:32px 24px 80px;}
.dash-header{display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;}
.dash-header h1{font-size:1.5rem;}
.dash-header-title{display:flex; align-items:center; gap:12px;}
.dash-logo{display:block; height:28px; width:auto;}
/* Actions on top, identity underneath - the signed-in account isn't an
   action, so it reads as a caption below the button row rather than
   floating between the page title and the buttons. */
.dash-header-right{display:flex; flex-direction:column; align-items:flex-end; gap:6px;}
.dash-header-actions{display:flex; align-items:center; gap:8px; flex-wrap:wrap; justify-content:flex-end;}
/* Highlighted (not the faint gray used elsewhere) - same treatment as the
   kiosk's signed-in email, for consistency across every header. */
.dash-user{font-size:.8rem; color:var(--accent-ink); font-weight:700;}

/* App identity label, stacked directly under the logo - the first thing
   anyone looks at, so "which app is this" (Student Dashboard vs.
   Staff Dashboard) reads immediately, reinforced by its color: it
   resolves through --accent-ink, so body.staff-mode's override (see :root)
   turns it plum automatically, in step with the rest of the page. */
.brand-block{display:flex; flex-direction:column; align-items:flex-start; gap:1px;}
.app-name-label{
  font-size:.7rem; font-weight:700; letter-spacing:.03em; text-transform:uppercase;
  color:var(--accent-ink); white-space:nowrap;
}

/* App switcher - dropdown in the dashboard header, same four apps as the
   post-login chooser (auth.js's showLandingChooser). Every item is a plain
   link (see dashboard.js's initAppSwitcherToggle) - only open/close is
   JS state here. */
.app-switcher{position:relative;}
.app-switcher-menu{
  position:absolute; top:calc(100% + 6px); right:0; z-index:20; min-width:210px;
  background:var(--surface); border:1px solid var(--rule); border-radius:10px;
  box-shadow:var(--shadow); padding:6px; display:flex; flex-direction:column; gap:2px;
}
/* Author styles beat the UA stylesheet's [hidden]{display:none} even at
   equal specificity, so the unconditional display:flex above silently wins
   and menu.hidden=true stops actually hiding anything without this - same
   fix .tag-menu[hidden] already needed. */
.app-switcher-menu[hidden]{display:none;}
.app-switcher-item{
  display:block; width:100%; text-align:left; background:none; border:none;
  padding:9px 12px; font-size:.88rem; color:var(--ink); text-decoration:none;
  border-radius:7px; cursor:pointer;
}
.app-switcher-item:hover{background:var(--surface-2);}
.app-switcher-item.active{background:var(--accent-soft); color:var(--accent-ink); font-weight:600;}
.app-switcher-divider{height:1px; background:var(--rule); margin:4px 2px;}

/* A segmented pill control on its own white shelf, rather than an
   underline-tab bar sitting directly on the page's solid blue background -
   every item (not just the active one) reads clearly as a distinct,
   clickable control against --bg this way. */
nav.dash-tabs{
  display:flex; gap:4px; flex-wrap:wrap; margin:20px 0 28px;
  background:var(--surface); border:1px solid var(--rule); border-radius:12px;
  padding:6px; box-shadow:var(--shadow);
}
nav.dash-tabs button{
  background:none; border:none; padding:10px 16px; font-size:.92rem;
  color:var(--ink-soft); cursor:pointer; border-radius:8px;
  transition:color .12s ease, background-color .12s ease, transform .08s ease;
}
nav.dash-tabs button:hover{color:var(--accent-ink); background:var(--surface-2);}
nav.dash-tabs button.active{color:#fff; background:var(--accent); font-weight:600;}
.dash-section{display:none;}
.dash-section.active{display:block;}

.table-wrap{overflow-x:auto; border:1px solid var(--rule); border-radius:10px; box-shadow:var(--shadow); margin-top:16px;}
table{width:100%; border-collapse:collapse; background:var(--surface); font-size:.92rem; min-width:520px;}
th,td{text-align:left; padding:10px 14px; border-bottom:1px solid var(--rule);}
thead th{background:var(--surface-2); font-size:.75rem; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft);}
tbody tr:last-child td{border-bottom:none;}

/* Students tab: wider spacing, zebra striping, and a bolder name column for quick scanning. */
table.students-table{font-size:1rem;}
table.students-table td, table.students-table th{padding:15px 18px;}
table.students-table tbody tr:nth-child(even){background:var(--surface-2);}
table.students-table td:first-child{font-weight:600;}
.row-actions{display:flex; gap:8px; flex-wrap:wrap;}
.roster-count{font-size:.85rem; color:var(--ink-faint);}

.toolbar{display:flex; gap:10px; flex-wrap:wrap; align-items:end; margin-bottom:8px;}
.field{display:flex; flex-direction:column; gap:4px;}
.field[hidden]{display:none;}
.field label{font-size:.78rem; color:var(--ink-soft);}
input,select{padding:9px 12px; border-radius:8px; border:1px solid var(--rule); background:var(--surface); color:var(--ink); font-size:.92rem;}
.btn-sm{
  padding:9px 16px; border-radius:8px; border:none; background:var(--accent); color:#fff;
  font-weight:600; cursor:pointer; font-size:.88rem;
  transition:filter .12s ease, transform .08s ease, background-color .15s ease, opacity .15s ease;
}
/* A solid --surface fill (not transparent) so outline buttons keep clear
   contrast against the app's solid blue page background (header/toolbar
   buttons like Open kiosk, Help, Sign out) - identical to transparent when
   they already sit on a white card/table row, so this only changes anything
   where contrast was actually missing. */
.btn-sm.outline{background:var(--surface); border:1px solid var(--rule); color:var(--ink-soft);}
/* The shadow specifically distinguishes buttons floating directly on the
   blue page background (header/toolbar) as elevated controls - skipped
   inside cards/tables/overlays, where a shadow per small button would just
   look cluttered against an already-white surface. */
.dash-header .btn-sm.outline, .toolbar .btn-sm.outline, .kiosk-header .btn-sm.outline{
  box-shadow:var(--shadow);
}
.btn-sm.danger{background:var(--error);}

/* Shared visual feedback for every button: press, hover, disabled/in-flight, and a brief
   success/error flash applied by UI.withFeedback() after an action completes.
   Press state is driven by ui.js (pointerdown/up -> .pressed class) rather than relying
   solely on CSS :active, which iOS Safari and other touch browsers don't reliably fire. */
.btn, .btn-sm, nav.dash-tabs button, li.result{ -webkit-tap-highlight-color: transparent; touch-action: manipulation; }

.btn:hover:not(:disabled), .btn-sm:hover:not(:disabled), nav.dash-tabs button:hover{
  filter:brightness(1.08);
}
.btn.pressed, .btn-sm.pressed, .btn:active:not(:disabled), .btn-sm:active:not(:disabled){
  transform:scale(0.94); filter:brightness(0.85);
}
nav.dash-tabs button.pressed, nav.dash-tabs button:active{
  background:var(--surface-2); transform:scale(0.97);
}
li.result.pressed, li.result:active{
  background:var(--surface-2); transform:scale(0.98);
}
.btn:disabled, .btn-sm:disabled, .btn.is-loading, .btn-sm.is-loading,
li.result.is-loading{
  opacity:.55; cursor:wait; pointer-events:none;
}
.btn.flash-success, .btn-sm.flash-success, li.result.flash-success{background:var(--success) !important; color:#fff !important; filter:none !important;}
.btn.flash-error, .btn-sm.flash-error, li.result.flash-error{background:var(--error) !important; color:#fff !important; filter:none !important;}

/* Dashboard's live-roster check-in search reuses the kiosk's .result/.pill
   markup, but the kiosk sizing (touch-target scale) is too large here. */
.dash-page .plain-list{margin:10px 0 20px;}
.dash-page .result{padding:10px 14px; font-size:.92rem; margin-bottom:6px; border-radius:8px;}
.dash-page .pill{font-size:.72rem; padding:3px 10px;}

.card{background:var(--surface); border:1px solid var(--rule); border-radius:10px; padding:20px; box-shadow:var(--shadow); margin-bottom:20px; max-width:480px;}
.card.wide{max-width:100%;}
.card h3{font-size:1rem; margin-bottom:14px;}
.card .field{margin-bottom:12px;}
.card input{width:100%;}

.hidden{display:none !important;}
a{color:var(--accent-ink);}

/* Shown only when window.APP_CONFIG.isTestEnvironment is true (env-banner.js) —
   pinned above everything, including the kiosk's fixed header, so the test
   stack is unmistakable from the live one at a glance. */
.env-banner{
  position:fixed; top:0; left:0; right:0; z-index:9999;
  background:var(--error); color:#fff; text-align:center;
  font-weight:700; letter-spacing:.04em; font-size:.8rem;
  padding:7px 12px;
}
body.has-env-banner{padding-top:34px;}
body.has-env-banner .kiosk-header{top:34px;}

/* Sign-in / new-password / kiosk-or-dashboard chooser (auth.js) - styled to
   match the marketing site's branding (same tokens, same logo, same button
   shape as marketing.css's .btn) rather than the internal dashboard's
   utilitarian .btn-sm/.card, since this is the first thing a customer sees. */
.auth-wrap{
  min-height:100%; display:flex; flex-direction:column; align-items:center;
  padding:64px 20px 40px;
}
.auth-brand{display:block; height:34px; width:auto; margin-bottom:32px;}
.auth-card{
  width:100%; max-width:420px; background:var(--surface); border:1px solid var(--rule);
  border-radius:14px; box-shadow:var(--shadow); padding:36px 32px; text-align:left;
}
.auth-title{font-size:1.5rem; font-weight:500; color:var(--accent-ink); text-align:center; margin:0 0 6px;}
.auth-subtitle{font-size:.92rem; color:var(--ink-soft); text-align:center; margin:0 0 26px;}
.auth-btn{
  display:block; width:100%; padding:13px 24px; border-radius:10px; border:none;
  font-size:1rem; font-weight:600; cursor:pointer; text-align:center; text-decoration:none;
  transition:filter .15s ease, transform .08s ease;
}
.auth-btn:hover:not(:disabled){filter:brightness(1.08);}
.auth-btn:active:not(:disabled){transform:scale(0.98);}
.auth-btn:disabled{opacity:.6; cursor:default;}
.auth-btn-primary{background:var(--accent); color:#fff; margin-top:6px;}
.auth-btn-secondary{background:var(--surface-2); color:var(--ink-soft); border:1px solid var(--rule);}
.auth-choices{display:flex; flex-direction:column; gap:12px; margin-top:22px;}
.auth-footer{margin-top:20px; text-align:center; font-size:.85rem;}

/* Birthdays — small emoji badge next to a name on Students/Live Roster
   (see js/ui.js birthdayInfo), plus the big check-in celebration banner
   (js/ui.js celebrateBirthday). No new icon assets - emoji glyphs keep this
   lightweight and legible at a glance. */
.birthday-icon{
  display:inline-block; margin-left:6px; font-size:.95rem;
  vertical-align:middle; cursor:default; line-height:1;
}
.birthday-banner{
  position:fixed; top:50%; left:50%; z-index:200; pointer-events:none;
  transform:translate(-50%, -50%) scale(0.7); opacity:0;
  background:linear-gradient(135deg, #ff8a00, #ff5da2);
  color:#fff; font-size:1.8rem; font-weight:700; text-align:center;
  padding:32px 48px; border-radius:20px; box-shadow:0 12px 40px rgba(0,0,0,.25);
  transition:opacity .3s ease, transform .3s ease; max-width:90%;
}
.birthday-banner.visible{opacity:1; transform:translate(-50%, -50%) scale(1);}

.center-select-overlay{position:fixed; inset:0; background:rgba(15,30,40,.55); display:flex; align-items:center; justify-content:center; z-index:100; padding:20px;}
.center-select-overlay[hidden]{display:none;}
.center-select-box{background:var(--surface); border-radius:12px; padding:28px; max-width:360px; width:100%; box-shadow:var(--shadow);}
.center-select-box h2{margin-bottom:8px; font-size:1.1rem;}
.center-select-box p{font-size:.85rem; color:var(--ink-soft); margin-bottom:18px;}
.center-select-list{display:flex; flex-direction:column; gap:10px;}
.center-select-list button{width:100%;}

/* Tags — the dropdown lives in the Students toolbar; the create/manage/
   select-students flows reuse the .center-select-overlay scrim+box pattern
   above rather than a new modal component. */
.tag-menu-wrap{position:relative;}
/* Flags the recommended-time-limit addition to Tags - links out to the
   marketing site's help page rather than opening anything in-app, so it
   stays a plain absolutely-positioned badge, not a tooltip/popup. */
.new-badge{
  position:absolute; top:-9px; right:-10px; z-index:1;
  background:#ff8a00; color:#fff; font-size:.62rem; font-weight:700;
  letter-spacing:.03em; text-transform:uppercase; text-decoration:none;
  padding:2px 7px; border-radius:999px; box-shadow:var(--shadow);
}
.new-badge:hover{filter:brightness(1.06);}

/* Dashboard-wide nudge toward Tags/Time-limit/Birthdays, separate from the
   .new-badge on the Tags button itself - this one's dismissible (localStorage,
   see dashboard.js initFeatureNotice) since it sits above every tab, not just
   Students, and shouldn't linger once someone's seen it. */
.feature-notice-bar{
  display:flex; align-items:center; gap:10px 20px; flex-wrap:wrap;
  background:var(--accent-soft); color:var(--accent-ink);
  border:1px solid var(--rule); border-radius:10px;
  padding:12px 16px; margin:0 0 16px;
}
.feature-notice-bar[hidden]{display:none;}
.feature-notice-text{flex:1; min-width:220px; font-size:.9rem; line-height:1.5;}
.feature-notice-links{display:flex; gap:16px; flex-wrap:wrap;}
.feature-notice-links a{color:var(--accent-ink); font-weight:600; font-size:.86rem; text-decoration:underline; white-space:nowrap;}
.feature-notice-dismiss{
  background:none; border:none; font-size:1.4rem; line-height:1; color:var(--accent-ink);
  cursor:pointer; padding:0 2px; flex:none; opacity:.7;
}
.feature-notice-dismiss:hover{opacity:1;}
.tag-menu{
  position:absolute; top:calc(100% + 6px); left:0; z-index:50; min-width:220px;
  background:var(--surface); border:1px solid var(--rule); border-radius:10px;
  box-shadow:var(--shadow); padding:8px;
}
.tag-menu[hidden]{display:none;}
.tag-menu-row{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  padding:8px 10px; border-radius:6px; border:none; background:none; cursor:pointer;
  font-size:.88rem; color:var(--ink);
}
.tag-menu-row:hover{background:var(--surface-2);}
.tag-menu-row .tag-swatch{width:10px; height:10px; border-radius:50%; flex-shrink:0;}
.tag-menu-empty{padding:8px 10px; font-size:.82rem; color:var(--ink-faint);}
.tag-menu-new{
  width:100%; margin-top:6px; padding:8px 10px; border-radius:6px;
  border:1px dashed var(--rule); background:none; cursor:pointer;
  font-size:.85rem; color:var(--accent-ink); font-weight:600;
}
.tag-menu-new:hover{background:var(--surface-2);}
.tag-menu-new:disabled{opacity:.5; cursor:not-allowed;}

/* Tag badge shown next to a student's name on the Student List and Live
   Roster tables — just a small colored dot. Hovering shows the tag's name
   in the app-styled .tag-tooltip popup below (see dashboard.js), not the
   browser's native title tooltip. */
.tag-dot{
  display:inline-block; width:11px; height:11px; border-radius:50%;
  margin-left:6px; vertical-align:middle; border:1px solid rgba(0,0,0,.15);
  cursor:default;
}

/* Popup shown on hovering a .tag-dot - fixed-positioned (from the dot's own
   bounding box, in JS) so it floats above the table's scroll container
   instead of getting clipped by .table-wrap's overflow. */
.tag-tooltip{
  position:fixed; z-index:60; pointer-events:none;
  background:var(--ink); color:var(--surface);
  font-size:.82rem; font-weight:600; padding:7px 12px; border-radius:8px;
  box-shadow:var(--shadow); white-space:nowrap;
  opacity:0; transform:translateY(4px);
  transition:opacity .12s ease, transform .12s ease;
}
.tag-tooltip.visible{opacity:1; transform:translateY(0);}
.tag-tooltip::after{
  content:""; position:absolute; left:50%; margin-left:-5px;
  top:100%; border:5px solid transparent; border-top-color:var(--ink);
}
.tag-tooltip.below::after{
  top:auto; bottom:100%; border-top-color:transparent; border-bottom-color:var(--ink);
}
/* Deliberately no display:flex here - that pulls a <td> out of the table's
   row-sizing algorithm in Chrome, making this cell's border-bottom land at a
   different height than its row siblings. The name span + .tag-dot spans are
   inline-level already, so plain inline flow lays them out and wraps fine. */
td.name-cell{line-height:1.6;}
/* Live Roster only - a student who's stayed past their time limit gets a
   slight red tint on their whole row's background - name text stays its
   normal color, this should read as a quiet flag, not an alarm. */
tr.over-time-limit{background:var(--error-soft);}

/* Tag filter chips (Students + Live Roster) - click one or more to show
   only rows carrying at least one selected tag. Empty (no tags yet for this
   center) collapses to nothing via the [hidden] attribute set in JS. */
.tag-filter-row{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px;}
.tag-filter-chip{
  display:inline-flex; align-items:center; gap:6px;
  padding:5px 12px; border-radius:999px; border:1px solid var(--rule);
  background:var(--surface); color:var(--ink-soft); font-size:.82rem; font-weight:600;
  cursor:pointer; transition:background-color .1s ease, color .1s ease, border-color .1s ease;
}
.tag-filter-chip:hover{border-color:var(--chip-color, var(--accent));}
.tag-filter-chip-dot{
  display:inline-block; width:9px; height:9px; border-radius:50%;
  background:var(--chip-color, currentColor); flex-shrink:0;
}
.tag-filter-chip.selected{background:var(--chip-color); border-color:var(--chip-color); color:#fff;}
.tag-filter-chip.selected .tag-filter-chip-dot{background:#fff;}

/* Full colored pill with the tag's name - used only where the tag itself
   is the subject (the manage-tag card header), not next to a student's
   name (see .tag-dot above for that). */
.tag-pill{
  display:inline-block; font-size:.72rem; font-weight:600; padding:2px 9px;
  border-radius:999px; margin-left:6px; color:#fff; vertical-align:middle;
}

/* Color swatch picker (create/edit tag form) - a fixed rainbow palette
   instead of a native color wheel, so every tag's color stays visually
   distinct and legible as a small dot. */
.tag-color-swatches{display:flex; flex-wrap:wrap; gap:8px; margin-top:2px;}
.tag-color-swatch{
  width:28px; height:28px; border-radius:50%; border:2px solid transparent;
  cursor:pointer; padding:0;
}
.tag-color-swatch.selected{border-color:var(--ink); box-shadow:0 0 0 2px var(--surface), 0 0 0 4px var(--ink);}
#tag-form-overlay textarea{width:100%; resize:vertical;}
.tag-form-actions{display:flex; gap:8px; margin-top:16px; flex-wrap:wrap;}

.tag-select-box{max-width:440px;}

/* Add a student / bulk import modal - wider than the default overlay box
   since it holds two full form sections, and scrolls internally rather
   than overflowing the viewport on shorter screens. */
.add-import-box{max-width:520px; max-height:85vh; overflow-y:auto;}
.add-import-divider{border:none; border-top:1px solid var(--rule); margin:26px 0;}
.tag-select-list{
  max-height:320px; overflow-y:auto; border:1px solid var(--rule); border-radius:8px;
  margin-top:6px;
}
.tag-select-row{
  display:flex; align-items:center; gap:10px; padding:8px 12px;
  border-bottom:1px solid var(--rule); font-size:.88rem;
}
.tag-select-row:last-child{border-bottom:none;}
.tag-select-row:nth-child(even){background:var(--surface-2);}
.tag-select-row input[type="checkbox"]{width:auto; margin:0;}
.tag-select-row label{flex:1; cursor:pointer;}
.tag-select-row.already-tagged{opacity:.6;}
.tag-select-row .already-tagged-note{font-size:.75rem; color:var(--ink-faint);}
