/*
 * Design tokens — single source of truth for color, spacing, radius,
 * shadow, typography and motion across the whole app. Every stylesheet in
 * the app should read from these custom properties rather than introducing
 * new magic numbers or one-off colors.
 *
 * Milestone 22 (mobile responsiveness): the app uses a single mobile-first
 * breakpoint at 600px (`@media (max-width: 600px)`), applied here and in
 * styles.css/ScheduleGrid.css. 600px sits comfortably above both target
 * phone widths (375px iPhone SE, 414px larger phones) with margin, while
 * staying well below tablet widths (768px+) where this app's desktop-style
 * layouts still read fine. The Electron shell's window has a hard
 * `minWidth: 960` (src/main/index.ts, unchanged), so it can never cross this
 * breakpoint — the rules below are inert there and only ever apply to the
 * web/PWA at phone width. A literal 600px is used directly in each media
 * query (custom properties aren't usable as media-query values).
 */

:root {
  /* ---- Neutral scale (warm slate) — light mode ---- */
  --gray-0: #ffffff;
  --gray-50: #faf6f0;
  --gray-100: #f1ece3;
  --gray-200: #e4dcd0;
  --gray-300: #d3c7b7;
  --gray-400: #ac9f8f;
  --gray-500: #8a7d6f;
  --gray-600: #6b6058;
  --gray-700: #4d443c;
  --gray-800: #362f29;
  --gray-900: #2b2420;

  /* ---- Amber accent scale — light mode ---- */
  --amber-50: #fdf2e3;
  --amber-100: #fbe4c2;
  --amber-300: #eab160;
  --amber-500: #d97706;
  --amber-600: #b45309;
  --amber-700: #92400e;

  /* ---- Semantic surfaces ---- */
  --color-bg: var(--gray-50);
  --color-surface: var(--gray-0);
  --color-surface-muted: var(--gray-100);
  --color-surface-raised: var(--gray-0);
  --color-text: var(--gray-900);
  --color-text-muted: var(--gray-600);
  --color-text-subtle: var(--gray-500);
  --color-border: var(--gray-200);
  --color-border-strong: var(--gray-300);

  /* ---- Accent (brand) ---- */
  --color-accent-subtle: var(--amber-50);
  --color-accent-muted: var(--amber-100);
  --color-accent: var(--amber-600);
  --color-accent-hover: var(--amber-700);
  --color-accent-active: var(--amber-700);
  --color-accent-contrast: #ffffff;
  --color-accent-text: var(--amber-700);

  /* ---- Semantic status colors (used consistently for success/warning/danger states) ---- */
  --color-success: #1e7a34;
  --color-success-bg: #e4f5e6;
  --color-success-border: #bfe4c4;

  --color-warning: #92620a;
  --color-warning-bg: #fbeecb;
  --color-warning-border: #f0d999;

  --color-danger: #b3261e;
  --color-danger-bg: #fbeceb;
  --color-danger-border: #f3c6c2;

  /* ---- Spacing scale ---- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;

  /* ---- Radius ---- */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-pill: 999px;
  /* Subtle corner rounding for the frameless main window itself (applied to
     #root below) — Windows 10 doesn't round frameless windows the way
     Windows 11 does, so the app clips its own corners in CSS. Deliberately
     small/subtle, distinct from the card-level --radius-lg. */
  --radius-window: 8px;

  /* ---- Shadow ---- */
  --shadow-xs: 0 1px 2px rgba(30, 20, 10, 0.06);
  --shadow-sm: 0 1px 3px rgba(30, 20, 10, 0.08);
  --shadow-md: 0 6px 20px rgba(30, 20, 10, 0.12);
  --shadow-lg: 0 16px 40px rgba(30, 20, 10, 0.18);

  /* ---- Typography ---- */
  --font-sans: 'Segoe UI', system-ui, -apple-system, sans-serif;
  --text-xs: 0.72rem;
  --text-sm: 0.85rem;
  --text-base: 0.95rem;
  --text-lg: 1.1rem;
  --text-xl: 1.35rem;
  --text-2xl: 1.7rem;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  /* ---- Motion ---- */
  --transition-fast: 130ms;
  --transition-base: 180ms;
  --transition-slow: 240ms;
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);

  /* ---- Focus ring ---- */
  --focus-ring-color: var(--amber-600);
  --focus-ring: 0 0 0 3px var(--color-accent-subtle), 0 0 0 1px var(--focus-ring-color);
}

:root[data-theme='dark'] {
  /* ---- Neutral scale — dark mode ----
     Milestone 11: re-anchored to the Mt Hood Lanes logo's deep forest green
     (sampled from the logo artwork as #19362b) rather than the generic warm
     slate used in earlier milestones. Hue drifts gradually from that forest
     green (~160°) at the dark/structural end of the scale toward the logo's
     cream/tan (~42°, sampled as #e0ccac) at the light/text end, so body text
     reads as a warm brand-appropriate cream instead of a flat off-white,
     while backgrounds/surfaces/borders read as a desaturated, sophisticated
     green-charcoal rather than a literal green wash. */
  --gray-0: #1b2823;
  --gray-50: #121c19;
  --gray-100: #24332c;
  --gray-200: #304138;
  --gray-300: #405446;
  --gray-400: #63735e;
  --gray-500: #8c957e;
  --gray-600: #b5b7a4;
  --gray-700: #ceccbb;
  --gray-800: #e2ded4;
  --gray-900: #f1efe9;

  /* ---- Amber/accent scale — dark mode ----
     Milestone 11: re-derived from the logo's brick-red/brown (sampled as
     #713025) rather than the earlier amber-on-black placeholder. The base
     brick hue is too dark/low-contrast to use verbatim as an interactive
     accent on a near-black background, so it's brightened and lifted for
     the mid/high steps (600/700) that carry buttons, links, active-tab
     text and the focus ring, while the low steps (50/100) stay dark, warm
     chip tints for subtle accent backgrounds. Variable names are unchanged
     (still --amber-*) since components only ever reference the semantic
     --color-accent-* tokens below, never the scale directly. */
  --amber-50: #32201a;
  --amber-100: #442a22;
  --amber-300: #cc8066;
  --amber-500: #ce5b3b;
  --amber-600: #b1492f;
  --amber-700: #d8775a;

  --color-bg: var(--gray-50);
  --color-surface: var(--gray-0);
  --color-surface-muted: var(--gray-100);
  --color-surface-raised: #202f29;
  --color-text: var(--gray-900);
  --color-text-muted: var(--gray-600);
  --color-text-subtle: var(--gray-500);
  --color-border: var(--gray-200);
  --color-border-strong: var(--gray-300);

  --color-accent-subtle: var(--amber-50);
  --color-accent-muted: var(--amber-100);
  --color-accent: var(--amber-600);
  --color-accent-hover: var(--amber-700);
  --color-accent-active: var(--amber-700);
  --color-accent-contrast: var(--gray-900);
  --color-accent-text: var(--amber-700);

  --color-success: #7fce93;
  --color-success-bg: #21351f;
  --color-success-border: #375a34;

  --color-warning: #f0c766;
  --color-warning-bg: #3a2e15;
  --color-warning-border: #5c4a20;

  --color-danger: #f2b8b5;
  --color-danger-bg: #3a2320;
  --color-danger-border: #5c332d;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.55);

  --focus-ring-color: var(--amber-700);
  --focus-ring: 0 0 0 3px var(--color-accent-subtle), 0 0 0 1px var(--focus-ring-color);
}

* {
  box-sizing: border-box;
}

html,
body,
#root {
  height: 100%;
}

body {
  margin: 0;
  /* Plain web/PWA default: a normal filled page background. The Electron
     shell overrides this to transparent below, since ITS window itself is
     transparent (see src/main/index.ts) so the corners #root clips show the
     desktop through, not a black/white rectangle. */
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.45;
  transition: color var(--transition-base) var(--ease-standard);
  /* Safety net, not a layout crutch: every horizontally-wide element in the
     app (the schedule grid, data tables) owns its own overflow-x:auto
     scroll container, so the page itself should never need to scroll
     sideways. This just guards against any stray 1px rounding/overflow
     rather than relying on it to hide a real layout bug. */
  overflow-x: hidden;
}

/* `is-electron-shell` is added to <body> at boot only when `window.api` is
   present (see main.tsx) — i.e. only inside the real Electron desktop app,
   never on the web/PWA, which has no window frame to fake rounded corners
   or transparency for. */
body.is-electron-shell {
  background-color: transparent;
}

#root {
  background-color: var(--color-bg);
  transition: background-color var(--transition-base) var(--ease-standard);
}

body.is-electron-shell #root {
  /* Visually rounds the frameless window's corners by clipping #root to the
     window bounds — see --radius-window. The window itself is transparent,
     so the four corner slivers outside this radius show the desktop behind
     the app rather than a hard-edged rectangle. */
  overflow: hidden;
  border-radius: var(--radius-window);
}

/* Consistent, visible keyboard focus everywhere — no component should rely
   on the browser default outline or suppress it without a replacement. */
:focus {
  outline: none;
}

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Respect the user's reduced-motion preference: collapse every transition
   and animation to effectively instant rather than removing the state
   change itself. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
/* ==========================================================================
   Layout shells: whole-window wrapper + title bar, boot loading screen,
   auth screens, app shell/nav, page content container.
   ========================================================================== */

/*
 * Fills the frameless main window exactly (`#root` is clipped to the window
 * bounds with `overflow: hidden` + `border-radius` — see theme.css — to give
 * the illusion of rounded corners on Windows 10, which doesn't round
 * frameless windows itself the way Windows 11 does). `.title-bar` is a fixed
 * strip at the top; whatever renders below it (the loading screen, an auth
 * screen, or the authenticated app shell) takes the remaining height and
 * scrolls internally rather than growing past the window and being clipped.
 */
.app-window {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.title-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 36px;
  padding: 0 var(--space-2) 0 var(--space-4);
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
  /* The drag region that lets the frameless window be moved (and, natively,
     maximized on double-click) — see WindowControls.tsx for the no-drag
     carve-out that keeps the buttons themselves clickable. */
  -webkit-app-region: drag;
}

.title-bar-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.title-bar-brand-mark {
  display: inline-flex;
  color: var(--color-accent);
  flex: 0 0 auto;
}

.window-controls {
  display: flex;
  align-items: stretch;
  gap: 2px;
  margin-left: auto;
  /* Carve this whole group back out of the title bar's drag region so the
     buttons stay clickable — see `.title-bar` above. */
  -webkit-app-region: no-drag;
}

.window-controls-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  transition:
    background-color var(--transition-fast) var(--ease-standard),
    color var(--transition-fast) var(--ease-standard);
}

.window-controls-btn:hover {
  background: var(--color-surface-raised);
  color: var(--color-text);
}

.window-controls-btn:focus-visible {
  outline: none;
  box-shadow: inset var(--focus-ring);
}

.window-controls-btn--close:hover {
  background: var(--color-danger);
  color: #fff;
}

.app-loading {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  color: var(--color-text-muted);
}

.auth-screen {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background:
    radial-gradient(circle at 15% 10%, var(--color-accent-subtle), transparent 45%), var(--color-bg);
}

.auth-screen-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 380px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-7);
  display: flex;
  flex-direction: column;
  gap: 6px;
  animation: rise-in var(--transition-slow) var(--ease-emphasized);
}

.auth-card h1 {
  margin: 0 0 4px;
  font-size: var(--text-xl);
  letter-spacing: -0.01em;
}

.auth-logo {
  display: block;
  width: 100%;
  max-width: 200px;
  height: auto;
  margin: 0 auto var(--space-3);
}

/* Visually hidden but present for screen readers/document structure — see
   LoginPage.tsx's h1 for the current usage. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.auth-subtitle {
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.install-app-prompt {
  width: 100%;
  max-width: 380px;
  margin-top: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.install-app-prompt-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.install-app-prompt-row svg {
  flex-shrink: 0;
  color: var(--color-accent);
}

.install-app-prompt p {
  margin: 0;
}

.app-shell {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/*
 * Milestone 22: `.app-nav` wraps two groups — `.app-nav-bar` (brand + the
 * mobile-only hamburger toggle) and `.app-nav-links` (every link, the theme
 * toggle, the user tag, logout). At desktop width both groups render as
 * `display: contents` — invisible to layout — so their children fall
 * straight into `.app-nav`'s own flex row exactly as before this
 * restructuring; the mobile breakpoint below turns them into a real
 * collapsible menu instead.
 */
.app-nav {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: var(--space-3) var(--space-5);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  flex-wrap: wrap;
}

.app-nav-bar,
.app-nav-links {
  display: contents;
}

.app-nav-toggle {
  display: none;
}

.app-nav-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: var(--font-weight-bold);
  margin-right: var(--space-5);
  color: var(--color-accent-text);
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.app-nav-brand-mark {
  display: inline-block;
  width: 26px;
  height: 26px;
  object-fit: contain;
  flex: 0 0 auto;
}

.app-nav-link {
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  transition:
    background-color var(--transition-fast) var(--ease-standard),
    color var(--transition-fast) var(--ease-standard);
}

.app-nav-link:hover {
  background: var(--color-surface-muted);
  color: var(--color-text);
}

.app-nav-link.active {
  background: var(--color-accent-subtle);
  color: var(--color-accent-text);
  font-weight: var(--font-weight-semibold);
}

.app-nav-spacer {
  flex: 1;
}

.app-nav-user {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-right: var(--space-2);
  white-space: nowrap;
}

.app-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-6);
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
  animation: fade-in var(--transition-slow) var(--ease-standard);
}

/* ==========================================================================
   Page scaffolding
   ========================================================================== */

.page h1 {
  margin-top: 0;
  font-size: var(--text-2xl);
  letter-spacing: -0.01em;
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-5);
  gap: var(--space-3);
  flex-wrap: wrap;
}

.page-header h1 {
  margin-bottom: 0;
}

.section {
  margin-bottom: var(--space-5);
}

.section-top {
  margin-top: var(--space-5);
}

.form-top-gap {
  margin-top: var(--space-4);
}

.tag-inline-gap {
  margin-left: var(--space-2);
}

.error-tight {
  margin-top: var(--space-1);
}

.section-subtitle {
  color: var(--color-text-muted);
  margin: -6px 0 var(--space-4);
  font-size: var(--text-sm);
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  padding: var(--space-5);
}

.card h2 {
  margin-top: 0;
  font-size: var(--text-lg);
}

/* ==========================================================================
   Forms
   ========================================================================== */

.field-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin-top: var(--space-3);
}

.text-input,
select.text-input,
textarea.text-input {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 400;
  margin-top: 4px;
  transition:
    border-color var(--transition-fast) var(--ease-standard),
    box-shadow var(--transition-fast) var(--ease-standard);
}

.text-input::placeholder {
  color: var(--color-text-subtle);
}

.text-input:hover:not(:disabled) {
  border-color: var(--color-border-strong);
}

.text-input:focus-visible {
  border-color: var(--focus-ring-color);
}

.text-input:disabled {
  opacity: 0.65;
  cursor: not-allowed;
}

.checkbox-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-base);
}

.checkbox-row input[type='checkbox'] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent);
}

.form-grid {
  display: grid;
  gap: 2px;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.form-error {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  margin-bottom: var(--space-2);
  animation: rise-in var(--transition-base) var(--ease-standard);
}

.form-success {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--color-success-bg);
  border: 1px solid var(--color-success-border);
  color: var(--color-success);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  margin-bottom: var(--space-2);
  animation: rise-in var(--transition-base) var(--ease-standard);
}

.color-swatch {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  vertical-align: middle;
}

.color-input {
  display: block;
  width: 64px;
  height: 36px;
  padding: 2px;
  margin-top: 4px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  cursor: pointer;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 9px 16px;
  font-size: var(--text-base);
  font-family: inherit;
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  background: var(--color-surface-muted);
  color: var(--color-text);
  transition:
    background-color var(--transition-fast) var(--ease-standard),
    border-color var(--transition-fast) var(--ease-standard),
    color var(--transition-fast) var(--ease-standard),
    transform var(--transition-fast) var(--ease-standard);
}

.btn:hover:not(:disabled) {
  background: var(--color-border);
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-accent-hover);
}

.btn-link {
  background: none;
  border-color: transparent;
  color: var(--color-accent-text);
  padding: 5px 8px;
}

.btn-link:hover:not(:disabled) {
  background: var(--color-accent-subtle);
}

.btn-danger {
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger);
}

.btn-danger:hover:not(:disabled) {
  background: var(--color-danger-border);
}

.btn-toggle {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
}

.btn-toggle:hover:not(:disabled) {
  color: var(--color-text);
  border-color: var(--color-border-strong);
}

.btn-toggle.active {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  border-color: var(--color-accent);
}

.assign-mode-toggle {
  display: flex;
  gap: 6px;
  margin: var(--space-4) 0;
}

/* ==========================================================================
   Tables
   ========================================================================== */

table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

table.data-table th,
table.data-table td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--color-border);
}

table.data-table th {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

table.data-table tbody tr {
  transition: background-color var(--transition-fast) var(--ease-standard);
}

table.data-table tbody tr:hover {
  background: var(--color-surface-muted);
}

table.data-table tbody tr:last-child td {
  border-bottom: none;
}

/* ==========================================================================
   Tags / badges — semantic status colors reused everywhere a status is shown.
   ========================================================================== */

.tag {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid transparent;
  white-space: nowrap;
}

.tag + .tag {
  margin-left: 4px;
}

.tag-accent {
  background: var(--color-accent-subtle);
  color: var(--color-accent-text);
  border-color: var(--color-accent-muted);
}

.tag-success {
  background: var(--color-success-bg);
  color: var(--color-success);
  border-color: var(--color-success-border);
}

.tag-warning {
  background: var(--color-warning-bg);
  color: var(--color-warning);
  border-color: var(--color-warning-border);
}

.tag-danger {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  border-color: var(--color-danger-border);
}

.tag-salaried {
  background: var(--color-accent-subtle);
  color: var(--color-accent-text);
  border-color: var(--color-accent-muted);
}

.tag-inactive {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  border-color: var(--color-danger-border);
}

.tag-timeoff {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  border: 1px solid var(--color-danger-border);
  display: block;
  width: fit-content;
  margin-bottom: var(--space-2);
}

.tag-status-pending {
  background: var(--color-warning-bg);
  color: var(--color-warning);
  border-color: var(--color-warning-border);
}

.tag-status-approved {
  background: var(--color-success-bg);
  color: var(--color-success);
  border-color: var(--color-success-border);
}

.tag-status-denied {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  border-color: var(--color-danger-border);
}

/* ==========================================================================
   Tabs (department tabs, time-off status filter)
   ========================================================================== */

.department-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--color-border);
}

.department-tab {
  position: relative;
  border: none;
  background: none;
  font-family: inherit;
  padding: 10px 18px;
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition:
    color var(--transition-fast) var(--ease-standard),
    border-color var(--transition-fast) var(--ease-standard);
}

.department-tab:hover {
  color: var(--color-text);
}

.department-tab.active {
  color: var(--color-accent-text);
  border-bottom-color: var(--color-accent);
}

/* ==========================================================================
   Week navigator
   ========================================================================== */

.week-nav {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

.week-nav-label {
  font-weight: var(--font-weight-semibold);
  min-width: 190px;
  text-align: center;
}

.week-nav-carryover {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.week-nav-carryover-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  white-space: nowrap;
}

.week-nav-carryover-select {
  min-width: 160px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--text-sm);
}

/* ==========================================================================
   My Schedule — a single employee's read-only day-by-day week view.
   ========================================================================== */

.my-schedule-days {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
}

.my-schedule-day {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.my-schedule-day-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 2px;
}

.my-schedule-day-label {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-base);
}

.my-schedule-status-tag {
  display: block;
  width: fit-content;
}

.my-schedule-off {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin: 0;
}

.my-schedule-shift {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.my-schedule-shift-department {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Shift cards are read-only here (no assign/edit dialog behind them) —
   drop the clickable affordance the schedule board's interactive grid uses. */
.my-schedule-day .shift-card {
  cursor: default;
}

.my-schedule-day .shift-card:hover {
  box-shadow: var(--shadow-xs);
  transform: none;
  background: var(--color-surface);
}

/* ==========================================================================
   Modals — fade + rise transitions on open.
   ========================================================================== */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 14, 8, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: var(--space-4);
  animation: fade-in var(--transition-base) var(--ease-standard);
}

.modal-card {
  width: 100%;
  max-width: 440px;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-6);
  animation: rise-in var(--transition-slow) var(--ease-emphasized);
}

.modal-card h2 {
  margin-top: 0;
  font-size: var(--text-lg);
}

.modal-subtitle {
  color: var(--color-text-muted);
  margin-top: -8px;
  font-size: var(--text-sm);
}

.shift-template-note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.unavailability-panel {
  background: var(--color-warning-bg);
  color: var(--color-warning);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: var(--text-sm);
}

.unavailability-panel ul {
  margin: var(--space-1) 0 0;
  padding-left: var(--space-4);
}

/* ==========================================================================
   Template picker (assign-shift dialog)
   ========================================================================== */

.template-picker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-height: 320px;
  overflow-y: auto;
}

.template-picker-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-surface-muted);
  color: var(--color-text);
  padding: 10px 12px;
  font-size: var(--text-base);
  font-family: inherit;
  cursor: pointer;
  transition:
    background-color var(--transition-fast) var(--ease-standard),
    transform var(--transition-fast) var(--ease-standard);
}

.template-picker-option:hover:not(:disabled) {
  background: var(--color-accent-subtle);
}

.template-picker-option:active:not(:disabled) {
  transform: scale(0.99);
}

.template-picker-option:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.template-picker-time {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  white-space: nowrap;
  margin-left: var(--space-3);
}

.anchor-time-field {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}

.custom-shift-form {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ==========================================================================
   Empty / loading states — every list/page shows one of these instead of a
   raw "Loading..." text node or a silently blank container.
   ========================================================================== */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-7) var(--space-4);
  color: var(--color-text-muted);
  animation: fade-in var(--transition-base) var(--ease-standard);
}

.empty-state-icon {
  display: inline-flex;
  line-height: 1;
  opacity: 0.75;
  color: var(--color-text-muted);
}

.empty-state-title {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  font-size: var(--text-base);
}

.empty-state-body {
  font-size: var(--text-sm);
  max-width: 360px;
}

.loading-state {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-2);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.spinner {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-accent);
  animation: spin 0.7s linear infinite;
  flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation-duration: 1.4s;
  }
}

/* ==========================================================================
   Keyframes
   ========================================================================== */

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ==========================================================================
   Mobile responsiveness (Milestone 22) — single breakpoint at 600px, see the
   comment atop theme.css for why. Two concerns are handled here:
   (1) layout — employee-facing screens (auth, My Schedule, Request Time
   Off, the AppLayout nav) get real phone-width layouts instead of just
   "doesn't overflow"; manager-only admin pages get a lighter pass so tables
   and forms aren't actively broken; (2) iOS/touch: form control font-size
   is bumped to 16px (below that, iOS Safari auto-zooms the whole page on
   focus) and small interactive elements get a ~44px minimum touch target.
   The Electron shell's window can't shrink below 960px wide (see
   src/main/index.ts), so none of this ever applies there.
   ========================================================================== */

@media (max-width: 600px) {
  /* ---- iOS zoom-on-focus fix — every text input/select/textarea ---- */
  .text-input,
  select.text-input,
  textarea.text-input {
    font-size: 16px;
  }

  /* ---- Touch targets — buttons, links-as-buttons, nav items, tabs ---- */
  .btn,
  .btn-link,
  .app-nav-link,
  .department-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }

  .btn-link {
    padding: 10px 12px;
  }

  .color-input {
    height: 44px;
  }

  input[type='checkbox'],
  input[type='radio'] {
    width: 20px;
    height: 20px;
  }

  .checkbox-row {
    min-height: 44px;
  }

  /* The "Closed" checkbox on the Store Hours admin table isn't wrapped in a
     label (see StoreHoursAdminPage.tsx's `.table-checkbox-tap`), so give its
     own wrapper a bigger tap area rather than relying on the ~20px box. */
  .table-checkbox-tap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
  }

  /* ---- Page chrome — reclaim side padding for narrow viewports ---- */
  .app-content {
    padding: var(--space-4);
  }

  /* ---- AppLayout nav — a manager's full link set (7 items) stacked
     one-per-row would eat almost the entire phone viewport before any page
     content is visible, so collapse it behind a hamburger toggle instead:
     the brand bar always shows, the link list opens as a full-width
     dropdown only on demand. ---- */
  .app-nav {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
  }

  .app-nav-bar,
  .app-nav-links.open {
    display: flex;
  }

  .app-nav-bar {
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
  }

  .app-nav-brand {
    margin: 0;
  }

  .app-nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    flex: 0 0 auto;
  }

  .app-nav-toggle:hover {
    background: var(--color-surface-muted);
  }

  .app-nav-links {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    padding: 0 var(--space-4) var(--space-3);
  }

  .app-nav-spacer {
    display: none;
  }

  .app-nav-link {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    box-sizing: border-box;
    padding: 12px var(--space-3);
  }

  .app-nav-user {
    margin: var(--space-2) 0 0;
  }

  .app-nav-links > .btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
  }

  /* ---- Auth screens (Login / First-run setup) ---- */
  .auth-screen {
    padding: var(--space-4);
  }

  .auth-card {
    padding: var(--space-5);
  }

  /* ---- Week navigator (My Schedule + Schedule Board) — the label's fixed
     min-width plus two buttons doesn't fit a phone width side by side, so
     put the label on its own full-width row and split the buttons evenly
     beneath it. ---- */
  .week-nav {
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .week-nav-label {
    order: -1;
    width: 100%;
    min-width: 0;
  }

  .week-nav .btn {
    flex: 1 1 0;
  }

  /* The carry-over group and the "all employees" button each need their own
     full-width row at phone width — they don't split evenly like the plain
     prev/next buttons above. */
  .week-nav-carryover {
    order: 1;
    width: 100%;
    margin-left: 0;
  }

  .week-nav-carryover-select {
    flex: 1 1 auto;
    min-width: 0;
  }

  .week-nav-carryover-all-btn {
    order: 2;
    width: 100%;
    flex: 1 1 100%;
  }

  /* ---- Data tables (time-off/unavailability history, admin CRUD lists) —
     scroll horizontally within the table itself rather than forcing the
     whole page to scroll sideways, the same fallback pattern already used
     for the manager Schedule Board's grid. ---- */
  table.data-table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  table.data-table th,
  table.data-table td {
    white-space: nowrap;
  }

  /* ---- Modals — reclaim padding at phone width ---- */
  .modal-overlay {
    padding: var(--space-3);
  }

  .modal-card {
    padding: var(--space-4);
  }
}

/* ==========================================================================
   PWA update toast (Milestone 23) — shown on the web/PWA build only, once a
   new deploy's service worker has taken over in the background (see
   src/renderer/src/pwa/pwaUpdate.ts). Fixed to the bottom of the viewport,
   centered, and deliberately small/quiet so it never blocks the app's own
   UI — a manager mid-edit on the Schedule Board should barely notice it
   until they choose to act on it.
   ========================================================================== */

.pwa-update-toast {
  position: fixed;
  left: 50%;
  bottom: var(--space-5);
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  max-width: calc(100vw - var(--space-6) * 2);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-raised);
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  animation: rise-in var(--transition-slow) var(--ease-emphasized);
}

.pwa-update-toast-message {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
}

.pwa-update-toast-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

.pwa-update-toast-refresh {
  padding: 6px 14px;
  font-size: var(--text-sm);
}

@media (max-width: 600px) {
  .pwa-update-toast {
    left: var(--space-4);
    right: var(--space-4);
    bottom: var(--space-4);
    transform: none;
    max-width: none;
    flex-wrap: wrap;
  }

  .pwa-update-toast-message {
    white-space: normal;
  }
}

/* ==========================================================================
   Print (Milestone 10) — the Schedule Board's "Print Schedule" button calls
   `window.print()` directly; there is no separate print-preview render. All
   interactive app chrome is hidden here so only PrintSchedule.tsx's
   purpose-built table (kept hidden on screen, shown here — see
   components/PrintSchedule/PrintSchedule.css) ends up on the page.
   ========================================================================== */

@media print {
  .title-bar,
  .app-nav,
  .page-header,
  .department-tabs,
  .week-nav,
  .overlap-banner,
  .schedule-grid-wrapper,
  .modal-overlay,
  .pwa-update-toast {
    display: none !important;
  }

  #root {
    overflow: visible !important;
    height: auto !important;
    border-radius: 0 !important;
    background: #fff !important;
  }

  body,
  .app-window,
  .app-shell,
  .app-content {
    height: auto !important;
    overflow: visible !important;
    background: #fff !important;
  }

  .app-content {
    padding: 0 !important;
    max-width: none !important;
    margin: 0 !important;
  }
}
/* ==========================================================================
   Card-based schedule grid — the core screen of the app. A CSS grid (not an
   HTML table) so each employee/day intersection reads as a comfortable
   card cell rather than a cramped spreadsheet cell, while still supporting
   proper grid semantics (role="grid") and keyboard navigation.
   ========================================================================== */

.schedule-grid-wrapper {
  overflow-x: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-2);
}

.schedule-grid {
  display: grid;
  min-width: 780px;
}

/*
 * Each row spans every column track via CSS Grid's `subgrid` (inheriting the
 * exact column sizing `.schedule-grid` defines inline) rather than the
 * simpler `display: contents` used before the drag-and-drop reordering
 * feature — `display: contents` gives a row no box at all, so it can't
 * receive the `transform`/`transition` a dragged row needs to visually lift
 * and glide between other rows. `grid-column: 1 / -1` makes the row itself
 * span the full width; `subgrid` then lets its own cells (the employee cell
 * + one per day) align to the parent's tracks exactly as before.
 */
.schedule-grid-row {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
}

/* ---- Header row ---- */

.schedule-grid-corner,
.schedule-grid-col-header {
  position: sticky;
  top: 0;
  background: var(--color-surface);
  z-index: 2;
  padding: var(--space-2) var(--space-3) var(--space-3);
}

.schedule-grid-corner {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  display: flex;
  align-items: flex-end;
}

.schedule-grid-col-header {
  border-radius: var(--radius-sm);
}

.schedule-grid-day-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.schedule-grid-day-header-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.schedule-grid-day-header-closed .schedule-grid-day-header-label {
  color: var(--color-text-muted);
}

/* ---- Employee row header ---- */

.schedule-grid-employee-cell {
  position: sticky;
  left: 0;
  background: var(--color-surface);
  z-index: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-weight: var(--font-weight-semibold);
  padding: var(--space-3);
  border-top: 1px solid var(--color-border);
  min-width: 160px;
}

/*
 * Drag handle for persistent Schedule Board row reordering — a dedicated
 * grip rather than the whole row/cell, so clicking the employee's name area
 * doesn't accidentally start a drag and clicking a day cell still opens its
 * assign/edit dialog normally. `touch-action: none` stops the browser from
 * treating a touch-drag on the handle as a page scroll gesture (this app is
 * used on phones — see Milestone 22); the ~44px touch target matches the
 * convention already used for other small interactive controls below.
 */
.schedule-grid-drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: -10px -8px -10px -12px;
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: grab;
  touch-action: none;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.schedule-grid-drag-handle:hover {
  color: var(--color-text);
  background: var(--color-surface-muted);
}

.schedule-grid-drag-handle:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--focus-ring-color);
}

.schedule-grid-drag-handle:active {
  cursor: grabbing;
}

.schedule-grid-employee-name {
  overflow-wrap: anywhere;
}

/* ---- Hours badges (day column header + closed states) ---- */

.hours-badge {
  display: inline-block;
  width: fit-content;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
}

.hours-badge-event {
  background: var(--color-accent-subtle);
  color: var(--color-accent-text);
  font-weight: var(--font-weight-semibold);
}

.hours-badge-closed {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  font-weight: var(--font-weight-semibold);
}

.hours-badge-unknown {
  font-style: italic;
}

/* ---- Grid cells ---- */

.schedule-grid-cell {
  min-width: 168px;
  padding: var(--space-2);
  border-top: 1px solid var(--color-border);
  border-left: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-radius: var(--radius-sm);
  transition: background-color var(--transition-fast) var(--ease-standard);
}

.schedule-grid-cell:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--focus-ring-color);
  background: var(--color-accent-subtle);
}

.schedule-grid-cell-blocked {
  background: var(--color-danger-bg);
}

.schedule-grid-day-header-closed {
  background: var(--color-surface-muted);
}

/* ---- Shift card ---- */

.shift-card {
  display: flex;
  flex-direction: column;
  width: 100%;
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--shift-color, var(--color-accent));
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  padding: 7px 9px;
  font-family: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition:
    transform var(--transition-fast) var(--ease-standard),
    box-shadow var(--transition-fast) var(--ease-standard),
    background-color var(--transition-fast) var(--ease-standard);
}

.shift-card:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
  background: var(--color-surface-muted);
}

.shift-card-time {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
}

.shift-card-edited,
.shift-card-template {
  margin-top: 1px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-subtle);
}

.shift-card-edited {
  color: var(--color-accent-text);
  font-weight: var(--font-weight-semibold);
}

.shift-card-tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 3px;
}

.shift-card-anchor-note {
  margin-top: 1px;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-style: italic;
}

/* ---- Preference indicator ---- */

.preference-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  font-size: 0.65rem;
  font-weight: var(--font-weight-bold);
  line-height: 1;
  cursor: default;
}

.preference-indicator-matches {
  background: var(--color-success-bg);
  color: var(--color-success);
}

.preference-indicator-partial {
  background: var(--color-warning-bg);
  color: var(--color-warning);
}

.preference-indicator-outside {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

/* ---- Add / assign trigger ---- */

.schedule-grid-add-cell {
  display: block;
  width: 100%;
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-text-muted);
  font-family: inherit;
  padding: 6px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition:
    border-color var(--transition-fast) var(--ease-standard),
    color var(--transition-fast) var(--ease-standard),
    background-color var(--transition-fast) var(--ease-standard);
}

.schedule-grid-add-cell:hover {
  border-color: var(--color-accent);
  border-style: solid;
  color: var(--color-accent-text);
  background: var(--color-accent-subtle);
}

.tag-timeoff-cell {
  align-self: flex-start;
}

/* ---- Overlap banner ---- */

.overlap-banner {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
  animation: rise-in var(--transition-base) var(--ease-standard);
}

.overlap-banner-title {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

.overlap-banner-list {
  margin: 0;
  padding-left: 20px;
  font-size: var(--text-sm);
}
/* ==========================================================================
   Print-only weekly schedule (Milestone 10) — a purpose-built table layout
   for physically posting one department's week, entirely separate from the
   on-screen `ScheduleGrid` CSS grid. `.print-schedule` stays hidden on
   screen and is revealed only inside `@media print` (the rest of the app's
   chrome is hidden the other way around — see the print rules at the bottom
   of styles.css). Colors here are hardcoded black/white/gray rather than
   the theme's custom properties: the printed page must stay legible on a
   grayscale printer regardless of whether the app is currently in light or
   dark mode on screen.
   ========================================================================== */

.print-schedule {
  display: none;
}

/* Landscape fits 7 day columns + an employee column far better than portrait. */
@page {
  size: landscape;
  margin: 12mm;
}

@media print {
  .print-schedule {
    display: block;
    color: #000;
    background: #fff;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  }

  .print-schedule-header {
    margin-bottom: 10px;
  }

  .print-schedule-title {
    margin: 0;
    font-size: 18pt;
    font-weight: 700;
    color: #000;
  }

  .print-schedule-subtitle {
    margin: 2px 0 0;
    font-size: 11pt;
    color: #222;
  }

  .print-schedule-empty {
    font-size: 11pt;
    color: #333;
  }

  .print-schedule-table {
    width: 100%;
    /* `separate` + zero spacing rather than `collapse`: with `collapse` on a
       fixed-layout table, Chromium's print rasterizer can round adjacent
       columns' shared border to zero width at certain column boundaries,
       silently dropping vertical lines (seen after the Employee, Monday, and
       Tuesday columns). Each cell drawing its own full border sidesteps that
       shared-border rounding entirely. */
    border-collapse: separate;
    border-spacing: 0;
    table-layout: fixed;
  }

  .print-schedule-table th,
  .print-schedule-table td {
    border: 1px solid #444;
    padding: 6px 8px;
    text-align: left;
    vertical-align: top;
    font-size: 9.5pt;
    color: #000;
  }

  .print-schedule-table thead {
    display: table-header-group;
    background: #eee;
  }

  .print-schedule-table tr {
    page-break-inside: avoid;
  }

  .print-schedule-employee-col {
    width: 13%;
    font-weight: 600;
  }

  .print-day-label {
    font-weight: 700;
    font-size: 10pt;
  }

  .print-day-hours {
    font-weight: 400;
    font-size: 8.5pt;
    color: #333;
    margin-top: 2px;
  }

  .print-shift + .print-shift {
    margin-top: 5px;
    padding-top: 5px;
    border-top: 1px dashed #999;
  }

  .print-shift-time {
    font-weight: 700;
  }

  .print-shift-labels {
    font-size: 8pt;
    font-style: italic;
    color: #333;
  }

  .print-shift-empty {
    color: #888;
  }
}
