/* ==========================================================================
   LC Waikiki Location Hub — design tokens
   Colours are PROVISIONAL (brief §07). They are not presented as LC Waikiki's
   official brand palette. Replace once the brand guideline is supplied.
   ========================================================================== */

:root {
  /* Brand */
  --brand-primary: #005EB8;
  --brand-primary-hover: #004E99;
  --brand-primary-soft: #E8F1FA;
  --brand-primary-border: #B8D4EC;

  /* Surfaces */
  --surface-canvas: #F5F7FA;
  --surface-card: #FFFFFF;
  --surface-sunken: #EDF0F5;
  --surface-hover: #F0F4F9;
  --surface-selected: #E8F1FA;

  /* Text */
  --text-primary: #172B4D;
  --text-secondary: #55688A;
  --text-muted: #7A8AA5;
  --text-inverse: #FFFFFF;
  --text-link: #0B5FA5;

  /* Borders */
  --border-default: #DCE1E9;
  --border-strong: #C2CAD6;
  --border-focus: #005EB8;

  /* Status */
  --status-success: #16794B;
  --status-success-soft: #E6F4EC;
  --status-success-border: #A9D5BC;
  --status-warning: #946200;
  --status-warning-soft: #FDF3E0;
  --status-warning-border: #E8CE9B;
  --status-danger: #B42318;
  --status-danger-soft: #FDECEA;
  --status-danger-border: #F0B8B2;
  --status-info: #0B5FA5;
  --status-info-soft: #E8F1FA;
  --status-info-border: #B8D4EC;
  --status-neutral: #55688A;
  --status-neutral-soft: #EEF1F6;
  --status-neutral-border: #D3DAE5;

  /* Typography */
  --font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Spacing — 4 / 8 px base */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;

  /* Radii */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;

  /* Elevation */
  --shadow-sm: 0 1px 2px rgba(23, 43, 77, .06);
  --shadow-md: 0 2px 6px rgba(23, 43, 77, .08);
  --shadow-lg: 0 8px 24px rgba(23, 43, 77, .12);

  /* Layout */
  --sidebar-width: 232px;
  --topbar-height: 56px;
  --control-height: 32px;
}

/* ==========================================================================
   Reset and base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--surface-canvas);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.3; }
h1 { font-size: 20px; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
p { margin: 0 0 var(--sp-3); }

a { color: var(--text-link); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Visible focus for keyboard users — WCAG 2.2 AA (brief §07). */
:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.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;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: var(--sp-2);
  z-index: 100;
  padding: var(--sp-2) var(--sp-4);
  background: var(--brand-primary);
  color: var(--text-inverse);
  border-radius: var(--radius-md);
}
.skip-link:focus { left: var(--sp-2); }

/* ==========================================================================
   Application shell
   ========================================================================== */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
}

.sidebar {
  background: #12263F;
  color: #C6D2E1;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border-bottom: 1px solid rgba(255, 255, 255, .1);
}

.sidebar__logo {
  border-radius: var(--radius-sm);
  flex: 0 0 34px;
  display: block;
}

.sidebar__brand-name {
  font-size: 14px;
  font-weight: 600;
  color: #FFFFFF;
  letter-spacing: .01em;
}

.sidebar__brand-sub {
  font-size: 11px;
  color: #8FA3BD;
  margin-top: 2px;
}

.sidebar__section {
  padding: var(--sp-4) var(--sp-4) var(--sp-1);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #7B90AC;
}

.sidebar__nav { flex: 1; padding-bottom: var(--sp-4); }

.sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  color: #C6D2E1;
  font-size: 13px;
  border-left: 2px solid transparent;
}
.sidebar__link:hover {
  background: rgba(255, 255, 255, .06);
  color: #FFFFFF;
  text-decoration: none;
}
.sidebar__link[aria-current="page"] {
  background: rgba(255, 255, 255, .1);
  color: #FFFFFF;
  border-left-color: #4A9BE0;
  font-weight: 500;
}

.sidebar__icon {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  opacity: .85;
  /* Belt and braces: an inline SVG defaults to 300x150 if any of the sizing
     rules above are lost, which turns the navigation into giant glyphs. */
  max-width: 16px;
  max-height: 16px;
  display: block;
}

/* Every inline icon is decorative and must never dictate layout. */
svg {
  flex-shrink: 0;
}

.sidebar__count {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  background: rgba(255, 255, 255, .14);
  color: #FFFFFF;
  padding: 1px 6px;
  border-radius: 9px;
}

.sidebar__footer {
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid rgba(255, 255, 255, .1);
  font-size: 11px;
  color: #7B90AC;
}

.main { display: flex; flex-direction: column; min-width: 0; }

/* ==========================================================================
   Topbar
   ========================================================================== */

.topbar {
  height: var(--topbar-height);
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0 var(--sp-6);
  position: sticky;
  top: 0;
  z-index: 20;
}

.topbar__scope {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2) var(--sp-1) var(--sp-3);
  background: var(--brand-primary-soft);
  border: 1px solid var(--brand-primary-border);
  border-radius: var(--radius-md);
  font-size: 13px;
}

.topbar__scope-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-secondary);
}

.topbar__scope select {
  border: 0;
  background: transparent;
  font: inherit;
  font-weight: 500;
  color: var(--text-primary);
  cursor: pointer;
  padding: 2px 4px;
}

.topbar__search { flex: 1; max-width: 420px; position: relative; }

/* The selector is deliberately doubled rather than left as
   `.topbar__search input`.
   A generic `input[type="search"]` rule further down the file sets
   `padding: 8px 12px` on every search field. An attribute selector outranks
   a class plus element, so that rule won on specificity regardless of the
   order, and the text started under the icon. Matching the element and the
   attribute here makes this rule the more specific one. */
.topbar__search input[type="search"] {
  width: 100%;
  height: var(--control-height);
  /* Clears the 16px icon, which sits at 12px and so ends at 28px. */
  padding: 0 var(--sp-3) 0 38px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font: inherit;
  font-size: 13px;
  background: var(--surface-canvas);
  color: var(--text-primary);
}

.topbar__search input[type="search"]:focus {
  background: var(--surface-card);
  border-color: var(--brand-primary);
}

.topbar__search-icon {
  position: absolute;
  left: 13px;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--text-muted);
  pointer-events: none;
  z-index: 2;
}

/* Suggestions under the search field. */
.search-results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 40;
  max-height: 360px;
  overflow-y: auto;
}

.search-results__group {
  padding: 6px 12px 2px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.search-results__item {
  display: block;
  padding: 7px 12px;
  font-size: 13px;
  color: var(--text-primary);
  border-left: 2px solid transparent;
}
.search-results__item:hover,
.search-results__item.is-active {
  background: var(--surface-hover);
  border-left-color: var(--brand-primary);
  text-decoration: none;
}
.search-results__meta {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 1px;
}
.search-results__empty {
  padding: 16px 12px;
  font-size: 12.5px;
  color: var(--text-muted);
  text-align: center;
}

.topbar__right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-3); }

.topbar__user {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-left: var(--sp-3);
  border-left: 1px solid var(--border-default);
}

.avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--brand-primary);
  color: #FFF;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
}

.topbar__user-meta { line-height: 1.25; }
.topbar__user-name { font-size: 12px; font-weight: 500; }
.topbar__user-role { font-size: 11px; color: var(--text-muted); }

/* Demo marker. Present on every screen (brief §18). */
.demo-flag {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--status-warning);
  background: var(--status-warning-soft);
  border: 1px solid var(--status-warning-border);
  padding: 2px 7px;
  border-radius: 3px;
  white-space: nowrap;
}

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

.page { padding: var(--sp-6); flex: 1; }

.page__head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  margin-bottom: var(--sp-5);
}

.page__title { font-size: 20px; font-weight: 600; }

.page__sub {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: var(--sp-1);
}

.page__actions { margin-left: auto; display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.breadcrumb {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: var(--sp-2);
}
.breadcrumb a { color: var(--text-muted); }

/* ==========================================================================
   Cards and grids
   ========================================================================== */

.card {
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.card__head {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.card__title { font-size: 14px; font-weight: 600; }
.card__sub { font-size: 12px; color: var(--text-muted); }
.card__body { padding: var(--sp-5); }
.card__body--flush { padding: 0; }
.card__actions { margin-left: auto; display: flex; gap: var(--sp-2); }

.grid { display: grid; gap: var(--sp-4); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Metric card — opens the matching filtered list when clicked. */
/* Metric cards -------------------------------------------------------------
   The first thing anyone looks at, so they carry a little more weight than a
   plain box: a colour bar that states the card's meaning before the number is
   read, an icon, and a number that counts up once on arrival.

   Every animation here is decoration over a value that is already correct in
   the markup, and all of it is switched off under prefers-reduced-motion. */

.metric {
  position: relative;
  display: block;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: var(--sp-4) var(--sp-5) var(--sp-4) calc(var(--sp-5) + 3px);
  box-shadow: var(--shadow-sm);
  color: inherit;
  overflow: hidden;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}

/* The bar states the card's meaning: blue is informational, amber needs
   attention, red has failed. It is colour plus position, never colour alone. */
.metric__bar {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
}

.metric:hover {
  border-color: var(--brand-primary-border);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  text-decoration: none;
}

.metric:active { transform: translateY(0); }

.metric__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}

.metric__icon {
  display: inline-flex;
  width: 26px;
  height: 26px;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--text-muted);
  flex: 0 0 26px;
  transition: background .15s, color .15s;
}

.metric__icon-svg { width: 14px; height: 14px; }

.metric:hover .metric__icon {
  background: var(--brand-primary-soft);
  color: var(--brand-primary);
}

.metric--warning:hover .metric__icon { background: var(--status-warning-soft); color: var(--status-warning); }
.metric--danger:hover .metric__icon  { background: var(--status-danger-soft);  color: var(--status-danger); }

/* A foot that carries a warning reads as one. */
.metric__flag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.metric__flag--warning { background: var(--status-warning-soft); color: var(--status-warning); }
.metric__flag--danger  { background: var(--status-danger-soft);  color: var(--status-danger); }

/* Arrival ------------------------------------------------------------------
   Cards rise in sequence, so the row reads left to right rather than appearing
   all at once. The delay is set from the index, so adding a card needs no new
   rule. */

.metrics[data-animate] .metric {
  opacity: 0;
  transform: translateY(8px);
  animation: metric-in .4s cubic-bezier(.2, .7, .3, 1) forwards;
}

.metrics[data-animate] .metric:nth-child(1) { animation-delay: .02s; }
.metrics[data-animate] .metric:nth-child(2) { animation-delay: .08s; }
.metrics[data-animate] .metric:nth-child(3) { animation-delay: .14s; }
.metrics[data-animate] .metric:nth-child(4) { animation-delay: .20s; }

@keyframes metric-in {
  to { opacity: 1; transform: translateY(0); }
}

/* While the value is counting, the number should not reflow as digits change
   width. tabular-nums is already set on .num; this keeps the box stable. */
.metric__value { min-height: 34px; }

/* Anyone who has asked their system not to animate things gets the final
   state immediately. This is not optional: a counting number can be
   disorienting and, for some people, a genuine accessibility problem. */
@media (prefers-reduced-motion: reduce) {
  .metrics[data-animate] .metric {
    opacity: 1;
    transform: none;
    animation: none;
  }

  .metric,
  .metric__icon {
    transition: none;
  }

  .metric:hover { transform: none; }
}

.metric__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.metric__value {
  font-size: 28px;
  font-weight: 600;
  margin-top: var(--sp-2);
  font-variant-numeric: tabular-nums;
}

.metric__foot {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: var(--sp-1);
}
.metric--warning .metric__value { color: var(--status-warning); }
.metric--danger .metric__value { color: var(--status-danger); }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: var(--control-height);
  padding: 0 var(--sp-3);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  background: var(--surface-card);
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, border-color .12s;
}
.btn:hover { background: var(--surface-hover); text-decoration: none; }
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
}

.btn--primary {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: var(--text-inverse);
}
.btn--primary:hover { background: var(--brand-primary-hover); border-color: var(--brand-primary-hover); }

.btn--danger { color: var(--status-danger); border-color: var(--status-danger-border); background: var(--status-danger-soft); }
.btn--ghost { border-color: transparent; background: transparent; }
.btn--ghost:hover { background: var(--surface-hover); }
.btn--sm { height: 26px; font-size: 12px; padding: 0 var(--sp-2); }

/* A control that cannot do real work is labelled, never left looking active. */
.btn--inert {
  pointer-events: none;
  opacity: .65;
}

.btn-group { display: inline-flex; gap: var(--sp-2); }

/* ==========================================================================
   Badges and status
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 500;
  padding: 2px 7px;
  border-radius: 3px;
  border: 1px solid transparent;
  white-space: nowrap;
  line-height: 1.5;
}

/* Every status carries a shape or text cue, never colour alone (WCAG). */
.badge::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 6px;
}
.badge--plain::before { display: none; }

.badge--success { color: var(--status-success); background: var(--status-success-soft); border-color: var(--status-success-border); }
.badge--warning { color: var(--status-warning); background: var(--status-warning-soft); border-color: var(--status-warning-border); }
.badge--danger  { color: var(--status-danger);  background: var(--status-danger-soft);  border-color: var(--status-danger-border); }
.badge--info    { color: var(--status-info);    background: var(--status-info-soft);    border-color: var(--status-info-border); }
.badge--neutral { color: var(--status-neutral); background: var(--status-neutral-soft); border-color: var(--status-neutral-border); }

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

.table-wrap { overflow-x: auto; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

table.data th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface-sunken);
  padding: var(--sp-3) var(--sp-3);
  border-bottom: 1px solid var(--border-default);
  white-space: nowrap;
  position: sticky;
  top: 0;
}

table.data td {
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border-default);
  vertical-align: middle;
}

table.data tbody tr:hover { background: var(--surface-hover); }
table.data tbody tr[aria-selected="true"] { background: var(--surface-selected); }

table.data .num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .mono { font-family: var(--font-mono); font-size: 12px; }
table.data .nowrap { white-space: nowrap; }

.table-empty {
  padding: var(--sp-10);
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}

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

.field { margin-bottom: var(--sp-4); }
.field > label { display: block; font-size: 12px; font-weight: 500; margin-bottom: var(--sp-1); }
.field__hint { font-size: 11px; color: var(--text-muted); margin-top: var(--sp-1); }

/* Every text-like control, matched by what they are rather than by an
   enumerated list of types.
   The list used to name each type and it fell out of date: url, tel and
   datetime-local were added to screens later and were never styled, so the
   Destination URL, the campaign schedule and the store phone number rendered
   as small unstyled boxes while everything around them was full width.
   Matching on :not([type=...]) means a new input type is styled the moment it
   is used. Checkboxes, radios, files and range keep their native look. */
/* :where() zeroes the specificity of everything inside it.
   Without it, each :not() adds a class-level point and the selector reaches
   (0,8,1) — enough to outrank .topbar__search input[type="search"] at (0,2,1)
   no matter where either rule sits in the file. That is exactly what happened:
   the search field rendered with 12px of left padding instead of 38px and the
   icon sat on top of the placeholder.
   A baseline rule should be easy to override; :where() makes it so. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="color"]),
select,
textarea) {
  font: inherit;
  font-size: 13px;
  width: 100%;
  min-height: var(--control-height);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  color: var(--text-primary);
}

/* A native date or time picker draws its own indicator, so leave room for it
   rather than letting the value run underneath. */
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"] {
  padding-right: 6px;
}

:where(input:not([type="checkbox"]):not([type="radio"]):focus),
:where(select:focus),
:where(textarea:focus) {
  border-color: var(--brand-primary);
  outline: 2px solid rgba(0, 94, 184, .18);
  outline-offset: 0;
}

textarea { min-height: 96px; resize: vertical; }

.checkbox, .radio { display: flex; align-items: flex-start; gap: var(--sp-2); font-size: 13px; }
.checkbox input, .radio input { margin-top: 3px; flex: 0 0 auto; width: auto; }

/* ==========================================================================
   Filters and toolbar
   ========================================================================== */

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-card);
}

.toolbar__group { display: flex; align-items: center; gap: var(--sp-2); }
.toolbar__spacer { margin-left: auto; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: 12px;
  padding: 3px var(--sp-2);
  border-radius: 12px;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
}

.tabs {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--border-default);
  padding: 0 var(--sp-5);
  background: var(--surface-card);
}

.tab {
  padding: var(--sp-3) var(--sp-3);
  font-size: 13px;
  color: var(--text-secondary);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tab:hover { color: var(--text-primary); text-decoration: none; }
.tab[aria-current="page"], .tab.is-active {
  color: var(--brand-primary);
  border-bottom-color: var(--brand-primary);
  font-weight: 500;
}
.tab__count {
  font-size: 11px;
  color: var(--text-muted);
  margin-left: var(--sp-1);
}

/* ==========================================================================
   Notices
   ========================================================================== */

.notice {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-md);
  border: 1px solid;
  font-size: 13px;
  margin-bottom: var(--sp-4);
}
.notice__icon { flex: 0 0 16px; margin-top: 1px; }
.notice__body { flex: 1; }
.notice__title { font-weight: 600; margin-bottom: 2px; }

.notice--info    { background: var(--status-info-soft);    border-color: var(--status-info-border);    color: var(--text-primary); }
.notice--warning { background: var(--status-warning-soft); border-color: var(--status-warning-border); color: var(--text-primary); }
.notice--danger  { background: var(--status-danger-soft);  border-color: var(--status-danger-border);  color: var(--text-primary); }
.notice--success { background: var(--status-success-soft); border-color: var(--status-success-border); color: var(--text-primary); }
.notice--neutral { background: var(--status-neutral-soft); border-color: var(--status-neutral-border); color: var(--text-primary); }

/* ==========================================================================
   Utilities
   ========================================================================== */

.muted { color: var(--text-muted); }
.secondary { color: var(--text-secondary); }
.small { font-size: 12px; }
.xsmall { font-size: 11px; }
.strong { font-weight: 600; }
.mono { font-family: var(--font-mono); }
.num { font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.center { text-align: center; }

.stack > * + * { margin-top: var(--sp-3); }
.stack-lg > * + * { margin-top: var(--sp-5); }
.row { display: flex; align-items: center; gap: var(--sp-2); }
.row--wrap { flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.spacer { margin-left: auto; }

.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-5 { margin-bottom: var(--sp-5); }

.hidden { display: none; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1280px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 1024px) {
  .app { grid-template-columns: 64px 1fr; }
  .sidebar__brand-sub, .sidebar__section, .sidebar__link span,
  .sidebar__count, .sidebar__footer { display: none; }
  .sidebar__link { justify-content: center; padding: var(--sp-3); }
  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 768px) {
  .page { padding: var(--sp-4); }
  .grid--4, .grid--3, .grid--2 { grid-template-columns: 1fr; }
  .topbar { padding: 0 var(--sp-4); gap: var(--sp-2); }
  .topbar__search { display: none; }
  .topbar__user-meta { display: none; }
  .page__head { flex-direction: column; }
  .page__actions { margin-left: 0; }
}

/* ==========================================================================
   Guided demo overlay
   A presenter aid. It floats above the application and never replaces it, so
   dismissing it leaves every screen fully usable by hand.
   ========================================================================== */

.tour {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 380px;
  max-height: 46vh;
  display: flex;
  flex-direction: column;
  /* Slightly translucent so the row underneath stays readable if the
     presenter needs to reference it without collapsing the panel. */
  background: rgba(18, 38, 63, .97);
  backdrop-filter: blur(2px);
  color: #E4EBF3;
  border-radius: var(--radius-lg);
  box-shadow: 0 12px 40px rgba(9, 20, 35, .38);
  z-index: 60;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   The tour panel must not hide the data it is describing.

   It sits bottom-right, and on wide tables that put it on top of the last
   columns. While the tour is open the page reserves space for it, so the
   presenter can point at a figure without the panel covering it.
   -------------------------------------------------------------------------- */

/* The panel floats over the page and the page is left completely alone.
   Two alternatives were tried and both looked wrong: narrowing the content
   column left a dead strip and squeezed tables, and reserving bottom space
   pushed content down for no visible reason. The panel is dismissible and
   collapsible instead, so the page needs no adjustment at all. */

.tour__head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid rgba(255, 255, 255, .1);
}

.tour__eyebrow {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #7FB2E0;
}

.tour__title {
  font-size: 14px;
  font-weight: 600;
  color: #FFFFFF;
  margin-top: 2px;
}

.tour__close {
  margin-left: auto;
  color: #8FA3BD;
  font-size: 15px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
}
.tour__close:hover { color: #FFFFFF; background: rgba(255,255,255,.1); text-decoration: none; }

.tour__progress {
  display: flex;
  gap: 4px;
  padding: var(--sp-3) var(--sp-4) 0;
}

.tour__dot {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .18);
}
.tour__dot.is-done { background: #4A9BE0; }
.tour__dot.is-current { background: #FFFFFF; }

.tour__body {
  padding: var(--sp-4);
  overflow-y: auto;
  flex: 1;
}

.tour__screen {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  color: #7FB2E0;
  margin-bottom: var(--sp-3);
}

.tour__block { margin-bottom: var(--sp-4); }
.tour__block:last-child { margin-bottom: 0; }

.tour__label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #7B90AC;
  margin-bottom: var(--sp-1);
}

.tour__text {
  font-size: 13px;
  line-height: 1.55;
  margin: 0;
  color: #E4EBF3;
}

.tour__block--say .tour__text {
  font-style: italic;
  color: #FFFFFF;
  border-left: 2px solid #4A9BE0;
  padding-left: var(--sp-3);
}

.tour__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid rgba(255, 255, 255, .1);
}

.tour__foot .btn {
  background: rgba(255, 255, 255, .1);
  border-color: rgba(255, 255, 255, .18);
  color: #FFFFFF;
}
.tour__foot .btn:hover { background: rgba(255, 255, 255, .18); }
.tour__foot .btn--primary {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
}
.tour__foot .btn--primary:hover { background: var(--brand-primary-hover); }
.tour__foot .btn--inert { opacity: .35; }

.tour__counter {
  margin: 0 auto;
  font-size: 11px;
  color: #8FA3BD;
  font-variant-numeric: tabular-nums;
}

.tour__foot--sub {
  padding-top: 0;
  border-top: 0;
  justify-content: space-between;
}
.tour__foot--sub a { color: #7FB2E0; }

@media (max-width: 1100px) {
  .tour { right: 12px; left: 12px; bottom: 12px; width: auto; max-height: 52vh; }
}

/* A presenter may still want the whole screen. This collapses the panel to
   its header so a wide table can be shown unobstructed. */
.tour.is-collapsed .tour__body,
.tour.is-collapsed .tour__foot,
.tour.is-collapsed .tour__progress { display: none; }
.tour.is-collapsed { max-height: none; }
.tour__collapse {
  margin-left: auto;
  color: #8FA3BD;
  font-size: 13px;
  line-height: 1;
  padding: 2px 6px;
  background: none;
  border: 0;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.tour__collapse:hover { color: #FFFFFF; background: rgba(255,255,255,.1); }

.tour__head-actions { margin-left: auto; display: flex; gap: 2px; align-items: center; }

/* ==========================================================================
   Demo access gate
   The first screen a client sees. It should look deliberate rather than like
   a browser popup, which is why this is a page and not HTTP basic auth.
   ========================================================================== */

.gate {
  display: grid;
  place-items: center;
  min-height: 100vh;
  background: #12263F;
  padding: var(--sp-5);
}

.gate__panel {
  width: 100%;
  max-width: 400px;
  background: var(--surface-card);
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 60px rgba(9, 20, 35, .45);
  padding: var(--sp-8) var(--sp-8) var(--sp-6);
}

.gate__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}

.gate__logo {
  border-radius: var(--radius-md);
  flex: 0 0 44px;
  display: block;
  box-shadow: 0 2px 8px rgba(18, 38, 63, .18);
}

.gate__name { font-size: 14px; font-weight: 600; color: var(--text-primary); }
.gate__product { font-size: 12px; color: var(--text-muted); }

.gate__title {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: var(--sp-2);
}

.gate__lede {
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.55;
  margin-bottom: var(--sp-5);
}

.gate__form .field { margin-bottom: var(--sp-4); }

/* Larger targets than the dense in-app forms: this screen is used once,
   often on a laptop trackpad, and should feel deliberate. */
.gate__form input {
  height: 40px;
  font-size: 13.5px;
  background: var(--surface-card);
  border-color: var(--border-strong);
}

.gate__form input:focus {
  border-color: var(--brand-primary);
  box-shadow: 0 0 0 3px rgba(0, 94, 184, .12);
  outline: none;
}

.gate__form label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: .01em;
}

.gate__submit {
  width: 100%;
  height: 38px;
  margin-top: var(--sp-2);
}

.gate__error {
  background: var(--status-danger-soft);
  border: 1px solid var(--status-danger-border);
  color: var(--status-danger);
  border-radius: var(--radius-md);
  padding: var(--sp-3);
  font-size: 12.5px;
  margin-bottom: var(--sp-4);
}

.gate__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-default);
  font-size: 11px;
  color: var(--text-muted);
}

/* ==========================================================================
   Asset upload
   The drop zone, preview and check list. The checks report real file
   properties read in the browser, not decorative ticks.
   ========================================================================== */

.upload {
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface-canvas);
  transition: border-color .12s, background .12s;
}

.upload.is-over {
  border-color: var(--brand-primary);
  background: var(--brand-primary-soft);
}

.upload__label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-8) var(--sp-5);
  cursor: pointer;
  text-align: center;
  margin: 0;
}

.upload__icon { width: 28px; height: 28px; color: var(--text-muted); }
.upload__title { font-size: 14px; font-weight: 500; color: var(--text-primary); }
.upload__hint { font-size: 12px; color: var(--text-muted); }

.upload__preview {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-4);
  margin-top: var(--sp-4);
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
}

.upload__thumb {
  width: 72px;
  height: 72px;
  flex: 0 0 72px;
  border-radius: var(--radius-md);
  background: var(--surface-sunken) center/cover no-repeat;
  border: 1px solid var(--border-default);
}

.upload__meta { flex: 1; min-width: 0; }

.upload__checks { margin-top: var(--sp-2); }

.upload__check {
  font-size: 12px;
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
}
.upload__check.is-ok { color: var(--status-success); }
.upload__check.is-bad { color: var(--status-danger); font-weight: 500; }

.upload__progress {
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border-default);
  background: var(--surface-sunken);
}

.upload__stage {
  font-size: 12.5px;
  color: var(--text-muted);
  padding: 3px 0 3px 20px;
  position: relative;
}
.upload__stage::before {
  content: "○";
  position: absolute;
  left: 0;
  color: var(--border-strong);
}
.upload__stage.is-done { color: var(--status-success); }
.upload__stage.is-done::before { content: "●"; color: var(--status-success); }

/* ==========================================================================
   Charts
   Inline SVG and CSS bars. No charting library: the figures are computed on
   the server so the chart is present in the HTML and survives being copied
   into a document.
   ========================================================================== */

.chart { width: 100%; height: auto; display: block; overflow: visible; }

.chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-3);
  font-size: 12px;
  color: var(--text-secondary);
}

.chart__legend-item { display: inline-flex; align-items: center; gap: 6px; }

.chart__swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: 0 0 10px;
}

/* Horizontal bars ---------------------------------------------------------- */

.bars { display: flex; flex-direction: column; gap: 7px; }

.bars__row {
  display: grid;
  grid-template-columns: 96px 1fr 52px;
  align-items: center;
  gap: var(--sp-3);
}

.bars__label {
  font-size: 12.5px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bars__track {
  height: 8px;
  background: var(--surface-sunken);
  border-radius: 4px;
  overflow: hidden;
}

.bars__fill {
  height: 100%;
  border-radius: 4px;
  min-width: 2px;
  transition: width .2s ease;
}

.bars__value {
  font-size: 12.5px;
  text-align: right;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* Stacked bars ------------------------------------------------------------- */

.stacked { display: flex; flex-direction: column; gap: 8px; }

.stacked__row {
  display: grid;
  grid-template-columns: 110px 1fr 76px;
  align-items: center;
  gap: var(--sp-3);
}

.stacked__label {
  font-size: 11.5px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stacked__track {
  display: flex;
  height: 14px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--surface-sunken);
}

/* A hairline between segments so adjacent colours stay distinguishable in
   greyscale printing. */
.stacked__part + .stacked__part { box-shadow: -1px 0 0 var(--surface-card); }

.stacked__value {
  font-size: 12.5px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Theme toggle
   Both icons are present and one is hidden by the active theme, so switching
   needs no JavaScript beyond setting the attribute.
   ========================================================================== */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  color: var(--text-secondary);
  cursor: pointer;
  flex: 0 0 32px;
}

.theme-toggle:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 1px;
}

.theme-toggle__icon { width: 15px; height: 15px; display: block; }

.theme-toggle__sun,
.theme-toggle__moon { display: none; }

/* Light theme offers the moon: the action is "go dark". */
[data-theme="light"] .theme-toggle__moon { display: block; }
[data-theme="dark"] .theme-toggle__sun { display: block; }

/* ==========================================================================
   Dark theme
   Only token values change. Every rule in app.css reads from these tokens,
   so there is no second set of component styles to keep in step.

   Applied when the document carries data-theme="dark". The theme is set on
   <html> by an inline script before first paint, so there is no flash of the
   wrong theme.
   ========================================================================== */

[data-theme="dark"] {
  /* Brand. The blue is lightened because the light-theme blue does not carry
     enough contrast against a dark surface for text or small icons. */
  --brand-primary: #4A9BE0;
  --brand-primary-hover: #6BB0EA;
  --brand-primary-soft: #16304D;
  --brand-primary-border: #2B5580;

  /* Surfaces. The canvas is darker than the card so cards still read as
     raised, which is the opposite of the light theme's relationship. */
  --surface-canvas: #0E1726;
  --surface-card: #16202F;
  --surface-sunken: #101A28;
  --surface-hover: #1D2A3C;
  --surface-selected: #16304D;

  /* Text */
  --text-primary: #E8EDF5;
  --text-secondary: #A8B6CB;
  --text-muted: #7B90AC;
  --text-inverse: #0E1726;
  --text-link: #7FB2E0;

  /* Borders */
  --border-default: #26344A;
  --border-strong: #35455F;
  --border-focus: #4A9BE0;

  /* Status. Each is lightened and given a dark soft background, because the
     light theme's soft backgrounds would glare and its foregrounds would
     disappear against a dark card. */
  --status-success: #4ADE94;
  --status-success-soft: #10301F;
  --status-success-border: #1F5C3C;

  --status-warning: #E8B44A;
  --status-warning-soft: #33260A;
  --status-warning-border: #6B4E14;

  --status-danger: #FF7B6E;
  --status-danger-soft: #351714;
  --status-danger-border: #7A2E26;

  --status-info: #7FB2E0;
  --status-info-soft: #16304D;
  --status-info-border: #2B5580;

  --status-neutral: #A8B6CB;
  --status-neutral-soft: #1D2A3C;
  --status-neutral-border: #35455F;

  /* Shadows read as depth through light in the light theme and through
     darkness here, so they are strengthened. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, .45);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, .55);
}

/* The sidebar is already dark in both themes, so it keeps its own values.
   This block exists to stop a future edit from "fixing" it to match the
   surface tokens. */
[data-theme="dark"] .sidebar { background: #0B1420; }

/* Form controls need an explicit colour scheme so the browser draws native
   widgets — date pickers, select arrows, scrollbars — to match. */
[data-theme="dark"] { color-scheme: dark; }

/* Print stays light regardless of the screen theme: a dark report is not
   what anyone wants on paper. */
@media print {
  [data-theme="dark"] {
    --surface-canvas: #FFFFFF;
    --surface-card: #FFFFFF;
    --surface-sunken: #F5F7FA;
    --text-primary: #172B4D;
    --text-secondary: #55688A;
    --text-muted: #7A8AA5;
    --border-default: #DCE1E9;
    --border-strong: #C2CAD6;
  }
}

/* ==========================================================================
   Field groups and the weekly hours editor
   A twenty-field form reads as four decisions when it is sectioned, and the
   hours belong in seven rows rather than one line of text.
   ========================================================================== */

.field-group {
  border: 0;
  border-top: 1px solid var(--border-default);
  padding: var(--sp-5) 0 0;
  margin: 0 0 var(--sp-5);
}

.field-group:first-of-type { border-top: 0; padding-top: 0; }

.field-group__legend {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0;
  margin-bottom: var(--sp-4);
}

.btn__icon { width: 13px; height: 13px; }

/* Weekly hours ------------------------------------------------------------- */

.hours {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.hours__head,
.hours__row {
  display: grid;
  grid-template-columns: 1fr 130px 130px 72px;
  align-items: center;
  gap: var(--sp-3);
  padding: 7px var(--sp-4);
}

.hours__head {
  background: var(--surface-sunken);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-default);
}

.hours__row + .hours__row { border-top: 1px solid var(--border-subtle, var(--border-default)); }

.hours__row:nth-child(odd) { background: var(--surface-card); }
.hours__row:nth-child(even) { background: var(--surface-canvas); }

.hours__day { font-size: 13px; color: var(--text-primary); }

.hours__row input[type="time"] {
  font: inherit;
  font-size: 12.5px;
  padding: 4px 6px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--surface-card);
  color: var(--text-primary);
  width: 100%;
}

.hours__closed { display: flex; justify-content: center; margin: 0; }

.hours__closed input { width: 15px; height: 15px; }

/* A closed day greys its own times rather than hiding them: the previous
   value should still be readable. */
.hours__row:has(input[data-hours-closed]:checked) input[type="time"] {
  opacity: .35;
  pointer-events: none;
}

/* ==========================================================================
   Checkbox lists — group membership and channel permissions
   ========================================================================== */

.checks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 4px;
}

.checks--inline {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.checks__item {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: 7px 10px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  cursor: pointer;
  margin: 0;
  font-weight: 400;
}

.checks__item:hover { border-color: var(--border-strong); background: var(--surface-hover); }

.checks__item input[type="checkbox"] {
  width: 15px;
  height: 15px;
  margin: 2px 0 0;
  flex: 0 0 15px;
}

.checks__label { display: block; font-size: 12.5px; color: var(--text-primary); }
.checks__meta { display: block; font-size: 11px; color: var(--text-muted); margin-top: 1px; }

/* A checked row reads as selected, so the state is visible without hunting
   for the tick. */
.checks__item:has(input[type="checkbox"]:checked) {
  border-color: var(--brand-primary-border);
  background: var(--brand-primary-soft);
}

.checks__item:has(input[type="checkbox"]:disabled) {
  opacity: .55;
  cursor: not-allowed;
}

/* ==========================================================================
   Scope selector
   The select posts to the session, and a flag appears when the scope is
   narrowed so the state is visible even on a wide toolbar.
   ========================================================================== */

.topbar__scope {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 0 0 auto;
  margin: 0;
}

.topbar__scope-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0;
  white-space: nowrap;
}

.topbar__scope select {
  width: auto;
  min-width: 150px;
  height: var(--control-height);
  padding: 0 var(--sp-6) 0 var(--sp-3);
  font-size: 12.5px;
  background-color: var(--surface-canvas);
}

/* A narrowed scope is a state worth noticing: every screen is filtered. */
.scope-flag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--brand-primary-soft);
  color: var(--brand-primary);
  border: 1px solid var(--brand-primary-border);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}

.scope-flag__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* ==========================================================================
   LC Waikiki lockup
   The wordmark is the company's own SVG. "Hub" is our product name, set as
   text so it can use the interface font and follow the theme.

   The glyphs carry no fill of their own, so they inherit `currentColor` and
   one file serves both themes.
   ========================================================================== */

.lcw-lockup {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
  color: var(--text-primary);
  line-height: 1;
}

.lcw-lockup__mark {
  display: block;
  flex: 0 0 auto;
  fill: currentColor;
  /* Nudged down so the wordmark's baseline sits with the word beside it. */
  transform: translateY(1px);
}

/* A thin rule separates their mark from our name, so "Hub" does not read as
   part of the trademark. */
.lcw-lockup__divider {
  width: 1px;
  flex: 0 0 1px;
  /* Matched to the mark's cap height rather than the row's, so it does not
     run taller than the letters it separates. */
  height: 17px;
  align-self: center;
  margin-top: -1px;
  background: currentColor;
  opacity: .22;
}

/* Inter Bold, tightened slightly: the wordmark's letters are set close
   together and default tracking looks loose beside them. */
.lcw-lockup__product {
  font-family: var(--font-sans);
  font-size: 1.02em;
  font-weight: 700;
  letter-spacing: -0.012em;
  line-height: 1;
  color: var(--brand-primary);
}

/* --- Sidebar -------------------------------------------------------------
   A dark surface in both themes, so the lockup is set light there. */

.sidebar__lockup {
  color: #FFFFFF;
  gap: 8px;
}

.sidebar__lockup .lcw-lockup__product {
  /* The brand blue is too dark on the sidebar's navy; this is the same hue
     lifted until it reads. */
  color: #7FB2E0;
}

.sidebar__lockup .lcw-lockup__divider { opacity: .3; }

/* --- Login gate ----------------------------------------------------------
   The card is a light surface in the light theme and a dark one in the dark
   theme, so this uses the theme tokens rather than fixed values. */

.gate__lockup {
  color: var(--text-primary);
  gap: 10px;
}

/* --- "Hub", and a small arrival ------------------------------------------
   Three letters do not need a flourish, so this is one gesture: the word
   fades up once, just after the mark has painted, and the accent underline
   draws in behind it. Both are decoration over text that is already there,
   and both stop under prefers-reduced-motion.

   The mark itself is deliberately still. It is the client's trademark and
   animating someone's logo is not a decision to make on their behalf. */

.lcw-lockup__product {
  position: relative;
  display: inline-block;
  /* Centring the boxes is not enough: the mark's SVG box is 19px tall while
     the word's line box is 14.28px, so their centres land 3.64px apart and the
     word reads as sitting low. This shifts the word's box to share the mark's
     centre. Measured, not guessed. */
  align-self: center;
  margin-top: 0.6px;
  animation: lockup-word-in .42s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: .12s;
}

/* A short rule under the word, drawn rather than placed, in the brand blue.
   It reads as an underline on a lockup, not as a second divider. */
.lcw-lockup__product::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 2px;
  border-radius: 1px;
  background: currentColor;
  opacity: .45;
  transform: scaleX(0);
  transform-origin: left center;
  animation: lockup-rule-in .5s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: .26s;
}

@keyframes lockup-word-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes lockup-rule-in {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* On the sidebar the word is already light on dark, so the rule carries the
   accent instead of the text colour. */
.sidebar__lockup .lcw-lockup__product::after { background: #7FB2E0; }

@media (prefers-reduced-motion: reduce) {
  .lcw-lockup__product,
  .lcw-lockup__product::after {
    animation: none;
  }

  .lcw-lockup__product::after { transform: scaleX(1); }
}

/* --- Login gate, lockup block -------------------------------------------- */

.gate__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: var(--sp-5);
}

.gate__lockup { color: var(--text-primary); }

.gate__tagline {
  font-size: 12px;
  color: var(--text-muted);
  letter-spacing: .01em;
}

/* The gate's own name and product lines are no longer used: the lockup and
   the tagline replace them. Kept harmless if something still references them. */

/* ==========================================================================
   User menu
   A single button opens a small panel with the signed-in identity and a
   sign-out action. The one thing a signed-in user always needs is a way out,
   and before this it was missing entirely.
   ========================================================================== */

.user-menu {
  position: relative;
}

.topbar__user {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 4px 8px 4px 6px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  font: inherit;
}

.topbar__user:hover {
  background: var(--surface-hover);
  border-color: var(--border-default);
}

.topbar__user:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 1px;
}

.topbar__user-meta {
  text-align: left;
  line-height: 1.2;
}

.topbar__user-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
}

.topbar__user-role {
  font-size: 11px;
  color: var(--text-muted);
}

.topbar__user-caret {
  display: inline-flex;
  align-items: center;
  color: var(--text-muted);
}

.topbar__user-caret-icon { width: 13px; height: 13px; }

.user-menu__panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 200px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  z-index: 50;
}

.user-menu__identity {
  padding: 8px 10px 10px;
  border-bottom: 1px solid var(--border-default);
  margin-bottom: 4px;
}

.user-menu__item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.user-menu__item:hover {
  background: var(--surface-hover);
}

.user-menu__item-icon { width: 14px; height: 14px; color: var(--text-muted); }

.user-menu__item:hover .user-menu__item-icon { color: var(--status-danger); }
