/*
  Dashboard v2 (maximalist pass)
  Path: css/dashboard-v2.css

  Load AFTER dashboard.css:
  <link rel="stylesheet" href="css/dashboard.css">
  <link rel="stylesheet" href="css/dashboard-v2.css">

  Reuses the motion tokens defined in register-v2.css (--ease-signature,
  --ease-snap, --dur-instant/quick/moment/scene). If register-v2.css is
  not loaded on this page, they're redefined here so this file never
  depends on load order across pages.
*/

:root {
  --ease-signature: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-snap: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-instant: 150ms;
  --dur-quick: 280ms;
  --dur-moment: 480ms;
  --dur-scene: 900ms;
}


.dash-greeting { margin-bottom: 20px; animation: dash-fade-up var(--dur-moment) var(--ease-signature) both; }
.dash-greeting .eyebrow { margin-bottom: 4px; }
@keyframes dash-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .dash-greeting { animation: none; } }

.dash-card-header { margin-bottom: 32px; animation: dash-fade-up var(--dur-moment) var(--ease-signature) both; }
.dash-hero-card { max-width: 420px; transform: rotate(-1deg); transition: transform var(--dur-moment) var(--ease-signature), box-shadow var(--dur-moment) var(--ease-signature); }
.dash-hero-card:hover { transform: rotate(0.4deg) translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .dash-greeting, .dash-card-header { animation: none; } }

.dash-stage-row { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; flex-wrap: wrap; }
.dash-stage-capsule { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 999px; background-color: var(--color-surface-raised); border: 1px solid var(--color-border); font-family: var(--font-mono); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.dash-stage-capsule .stage-dot { width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-warning); box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.18); }
.dash-stage-capsule.is-approved { border-color: rgba(122, 155, 118, 0.4); color: var(--color-sage); }
.dash-stage-capsule.is-approved .stage-dot { background-color: var(--color-sage); box-shadow: 0 0 0 3px rgba(122, 155, 118, 0.18); }
.dash-stage-capsule.is-attention { border-color: rgba(193, 67, 47, 0.35); color: var(--color-danger); }
.dash-stage-capsule.is-attention .stage-dot { background-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(193, 67, 47, 0.18); }

.dash-status-chips { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
.dash-status-chip { display: inline-flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: var(--radius-md); border: 1px solid var(--color-border); background-color: var(--color-surface); font-size: var(--fs-sm); transition: border-color var(--dur-quick) var(--ease-signature), background-color var(--dur-quick) var(--ease-signature); }
.dash-status-chip .chip-icon { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; background-color: var(--color-warning-bg); color: var(--color-warning); }
.dash-status-chip.is-complete { border-color: rgba(122, 155, 118, 0.35); background-color: var(--color-success-bg); }
.dash-status-chip.is-complete .chip-icon { background-color: transparent; color: var(--color-sage); }
.dash-status-chip.is-complete .chip-icon svg path { stroke-dasharray: 20; stroke-dashoffset: 20; animation: dash-check-draw var(--dur-moment) var(--ease-snap) forwards; }
@keyframes dash-check-draw { to { stroke-dashoffset: 0; } }
.dash-status-chip .chip-label { font-weight: 600; }
.dash-status-chip .chip-sub { color: var(--color-text-muted); font-size: var(--fs-xs); }
@media (prefers-reduced-motion: reduce) { .dash-status-chip.is-complete .chip-icon svg path { animation: none; stroke-dashoffset: 0; } }

.dash-section.dash-stagger { opacity: 0; transform: translateY(14px); animation: dash-fade-up var(--dur-moment) var(--ease-signature) both; }
@media (prefers-reduced-motion: reduce) { .dash-section.dash-stagger { animation: none; opacity: 1; transform: none; } }

.dash-field-grid.is-save-pulse, .dash-details-block.is-save-pulse { animation: dash-save-pulse var(--dur-scene) var(--ease-signature); }
@keyframes dash-save-pulse { 0% { box-shadow: 0 0 0 0 rgba(122, 155, 118, 0); } 20% { box-shadow: 0 0 0 4px rgba(122, 155, 118, 0.16); } 100% { box-shadow: 0 0 0 0 rgba(122, 155, 118, 0); } }
@media (prefers-reduced-motion: reduce) { .dash-field-grid.is-save-pulse, .dash-details-block.is-save-pulse { animation: none; } }
.dash-save-check { display: inline-flex; align-items: center; gap: 8px; color: var(--color-sage); font-weight: 600; }
.dash-save-check svg path { stroke-dasharray: 20; stroke-dashoffset: 20; animation: dash-check-draw var(--dur-moment) var(--ease-snap) 0.1s forwards; }
@media (prefers-reduced-motion: reduce) { .dash-save-check svg path { animation: none; stroke-dashoffset: 0; } }

.locked-field-row { transition: border-color var(--dur-quick) var(--ease-signature); }
.locked-field-in-progress { display: inline-flex; align-items: center; gap: 8px; margin-top: 6px; font-size: var(--fs-xs); color: var(--color-text-muted); }
.locked-field-in-progress .progress-dot { width: 6px; height: 6px; border-radius: 50%; background-color: var(--color-accent); animation: dash-dot-breathe var(--dur-scene) ease-in-out infinite; }
@keyframes dash-dot-breathe { 0%, 100% { opacity: 0.4; transform: scale(0.85); } 50% { opacity: 1; transform: scale(1.1); } }
@media (prefers-reduced-motion: reduce) { .locked-field-in-progress .progress-dot { animation: none; opacity: 0.8; } }
.request-change-form { transition: none; }
.request-change-form.is-open { animation: dash-form-open var(--dur-moment) var(--ease-snap) both; }
@keyframes dash-form-open { from { opacity: 0; transform: translateY(-6px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
@media (prefers-reduced-motion: reduce) { .request-change-form.is-open { animation: none; } }
.locked-field-ask-btn { background: none; border: none; color: var(--color-accent); font-weight: 600; font-size: var(--fs-sm); padding: 6px 4px; }
.locked-field-ask-btn:hover { text-decoration: underline; }

.announcement-card { position: relative; transition: border-color var(--dur-quick) var(--ease-signature); }
.announcement-card.is-unread { border-left-color: var(--color-accent); background-color: color-mix(in srgb, var(--color-accent) 5%, var(--color-surface)); }
.announcement-unread-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background-color: var(--color-accent); margin-right: 8px; animation: dash-dot-breathe var(--dur-scene) ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .announcement-unread-dot { animation: none; } }

.feedback-rating-option { transition: border-color var(--dur-quick) var(--ease-signature), background-color var(--dur-quick) var(--ease-signature), color var(--dur-quick) var(--ease-signature), transform var(--dur-instant) var(--ease-snap); }
.feedback-rating-option.is-selected { animation: dash-rating-pop var(--dur-quick) var(--ease-snap); }
@keyframes dash-rating-pop { 0% { transform: scale(0.85); } 60% { transform: scale(1.12); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .feedback-rating-option.is-selected { animation: none; } }

/* ================================================================
   STAGE 1 additions — structure & layout
   Everything below is new for the dashboard overhaul. No motion is
   introduced in this stage beyond what already existed above; these
   rules are pure layout/hierarchy. Reuses .card, .glass-panel, the
   --stitch token, and the reg-* brand mark pattern already
   established on index.html / register.html, so the dashboard reads
   as the same product rather than a fourth visual language.
   ================================================================ */

/* ---------- Page-level: brand mark + restrained photo accent ---------- */

.dash-shell-wrap {
  position: relative;
  overflow: hidden;
}

.dash-brand-mark {
  position: absolute;
  top: -10%;
  right: -4%;
  width: clamp(420px, 44vw, 680px);
  transform: rotate(-9deg);
  z-index: 0;
  pointer-events: none;
  opacity: 0.27;
}

.dash-brand-mark svg { width: 100%; height: auto; display: block; }
.dash-brand-mark svg .mark-fill { fill: var(--color-primary); fill-opacity: 1; }

html[data-theme="dark"] .dash-brand-mark { opacity: 0.1; }

@media (max-width: 860px) {
  .dash-brand-mark {
    width: clamp(320px, 70vw, 460px);
    top: -4%;
    right: -22%;
    opacity: 0.25;
  }
}

/* Photo accent: a quiet, desaturated strip behind the greeting only,
   not a hero bleed. This is a dashboard someone returns to for
   status, not a persuasion surface, so the photo stays a background
   texture that reinforces "this is the same portal you registered
   through" rather than competing with the card or status chips for
   attention. Heavily masked on both edges and darkened under text. */

.dash-photo-accent {
  position: absolute;
  top: 0;
  right: 0;
  width: min(46vw, 620px);
  height: 320px;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0.5;
}

.dash-photo-accent img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 30%;
  filter: grayscale(0.55) contrast(0.96);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, black 38%, black 70%, transparent 100%),
                       linear-gradient(180deg, black 0%, black 55%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(90deg, transparent 0%, black 38%, black 70%, transparent 100%),
              linear-gradient(180deg, black 0%, black 55%, transparent 100%);
  mask-composite: intersect;
}

html[data-theme="dark"] .dash-photo-accent { opacity: 0.28; }

@media (max-width: 860px) {
  .dash-photo-accent { display: none; }
}

/* ---------- Two-column layout: sticky status rail + main column ---------- */
/* Mirrors the registration flow's .reg-layout-grid / .reg-card-rail
   split: a persistent "who you are and where you stand" rail beside
   the actionable content, rather than one long undifferentiated
   stack. This is the single biggest structural change this pass
   makes, since it's what let the old dashboard read as five
   disconnected sections rather than one page with a clear job. */

.dash-layout-grid {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 40px;
  align-items: start;
  position: relative;
  z-index: 1;
}

@media (max-width: 960px) {
  .dash-layout-grid {
    grid-template-columns: 1fr;
  }
}

.dash-rail {
  position: sticky;
  top: 88px;
}

@media (max-width: 960px) {
  .dash-rail {
    position: static;
    margin-bottom: 8px;
  }
}

.dash-main {
  min-width: 0;
}

/* Status card: contains the stage capsule + parallel chips directly
   under the hero card, inside one visually contained unit, instead
   of floating loose beneath it as separate elements competing with
   the page background. */

.dash-status-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 20px;
  background-color: var(--color-surface);
  box-shadow: var(--shadow-soft);
}

.dash-status-card .dash-stage-row { margin-bottom: 16px; }
.dash-status-card .dash-status-chips { margin-bottom: 0; flex-direction: column; }
.dash-status-card .dash-status-chip { width: 100%; }

/* ---------- Section panels ---------- */
/* Each former "plain stack of sections" becomes a contained card
   with an icon-led header. The icon differentiates by content type
   (edit / lock / message / feedback) since these four sections run
   in parallel, not in sequence, so a numbered 01/02/03/04 marker
   would encode an order that doesn't actually exist here. */

.dash-panel {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  padding: 32px;
  box-shadow: var(--shadow-soft);
  margin-bottom: 28px;
}

.dash-panel:last-child { margin-bottom: 0; }

.dash-panel-header {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 24px;
}

.dash-panel-icon {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  background-color: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--color-accent);
}

.dash-panel-heading h3 { margin-bottom: 2px; }
.dash-panel-heading .section-hint { margin-bottom: 0; }

@media (max-width: 640px) {
  .dash-panel { padding: 24px 20px; }
}

/* ---------- Mobile topbar: icon-only theme toggle replaces sign out ---------- */
/* On mobile the navbar-actions row is tight (hamburger already lives
   there), and sign out is still one tap away inside the mobile nav
   panel, so it doesn't need a second home in the topbar. Swapping it
   for an icon-only theme toggle here means a camper can flip modes
   without opening the menu at all, reusing the exact
   .theme-toggle-icon pattern already shipped on register.html rather
   than inventing a second control language. Hidden on desktop, where
   the labeled .theme-toggle already covers this. */

.theme-toggle-icon {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background-color: var(--color-surface-raised);
  color: var(--color-text);
  transition: border-color var(--dur-quick) var(--ease-signature),
              transform var(--dur-quick) var(--ease-snap),
              background-color var(--dur-quick) ease;
}

.theme-toggle-icon:active { transform: scale(0.92); }

.theme-toggle-icon svg {
  transition: opacity var(--dur-quick) ease, transform var(--dur-moment) var(--ease-snap);
}

.theme-toggle-icon .icon-moon { display: none; }
html[data-theme="dark"] .theme-toggle-icon .icon-sun { display: none; }
html[data-theme="dark"] .theme-toggle-icon .icon-moon { display: block; }
html[data-theme="dark"] .theme-toggle-icon { border-color: rgba(232, 99, 47, 0.3); }

@media (max-width: 860px) {
  .theme-toggle-icon { display: flex; }
}

/* Old .dash-section spacing no longer needed now sections are panels
   with their own padding/margin; header/hint spacing moved into
   .dash-panel-header and .dash-panel-heading above. */
.dash-section.dash-panel h3,
.dash-section.dash-panel .section-hint {
  margin-bottom: 0;
}

/* ================================================================
   STAGE 2 additions — component redesign
   Restyles the four panel bodies as distinct, purpose-built
   components instead of default-styled form blocks. Still no motion
   beyond what Stage 1 already carried forward; timing/easing tokens
   used below are reused from the definitions above, not new ones.
   ================================================================ */

/* ---------- "Your details": grouped fields, medical callout ---------- */

.dash-field-subhead {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-weight: 700;
  margin-bottom: 12px;
}

.dash-medical-callout {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-raised);
  margin-top: 4px;
  margin-right: 2px;
}

.dash-medical-callout-icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: var(--color-danger-bg);
  color: var(--color-danger);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 2px;
  margin-left: -20px;
}

/* ---------- Locked fields: quiet list, not a stack of boxed forms ---------- */
/* A shared bordered surface with hairline dividers between rows reads
   as "one record" rather than "three separate forms," which matches
   the softer, less bureaucratic framing the locked-field copy already
   uses. Each row keeps its own request-change-form directly beneath
   it in DOM order (unchanged from Stage 1/original), so the divider
   sits only between a row and the NEXT row, not between a row and its
   own expanding form. */

.locked-field-list {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background-color: var(--color-surface);
}

.locked-field-list .locked-field-row {
  border: none;
  border-radius: 0;
  background: none;
  margin-bottom: 0;
  border-bottom: 1px solid var(--color-border);
  padding: 16px 18px;
}

.locked-field-list .locked-field-row:last-of-type {
  border-bottom: none;
}

/* When a row's request-change-form is open, it visually belongs to
   the row above it, so drop that row's divider while the form is
   showing rather than drawing a hairline between a question and its
   own answer field. */
.locked-field-list .request-change-form.is-open + .locked-field-row,
.locked-field-list .locked-field-row:has(+ .request-change-form.is-open) {
  border-bottom: none;
}

.locked-field-list .request-change-form {
  border: none;
  border-radius: 0;
  border-top: 1px dashed var(--color-border);
  border-bottom: 1px solid var(--color-border);
  background-color: var(--color-surface-raised);
  margin-top: 0;
}

.locked-field-list .request-change-form:last-child {
  border-bottom: none;
}

.locked-field-main {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.locked-field-icon {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-color: var(--color-surface-raised);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}

/* ---------- Announcements: feed rail + designed empty state ---------- */

.announcement-feed {
  position: relative;
  padding-left: 20px;
}

.announcement-feed::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 6px;
  bottom: 6px;
  width: 1px;
  background-color: var(--color-border);
}

.announcement-feed .announcement-card {
  position: relative;
}

.announcement-feed .announcement-card::before {
  content: '';
  position: absolute;
  left: -20px;
  top: 20px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: var(--color-border);
  border: 2px solid var(--color-surface);
  box-shadow: 0 0 0 1px var(--color-border);
}

.announcement-feed .announcement-card.is-unread::before {
  background-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

/* ---------- Shared: designed empty state ---------- */
/* Used wherever a section has nothing to show yet. Gives the "no data"
   moment a shape instead of a single line of gray text, per the
   brief's cheap-but-portal-wide-impact note on empty states. */

.dash-empty-state {
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  padding: 28px 20px;
  text-align: center;
}

.dash-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background-color: var(--color-surface-raised);
  color: var(--color-text-muted);
  margin-bottom: 12px;
}

.dash-empty-title {
  font-weight: 600;
  margin-bottom: 4px;
}

/* ---------- Feedback: scale labels + redesigned submitted state ---------- */

.feedback-scale-labels {
  display: flex;
  justify-content: space-between;
  max-width: 260px;
  margin-top: -10px;
  margin-bottom: 20px;
}

.feedback-scale-labels span {
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

.feedback-submitted-note {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  background-color: var(--color-success-bg);
  color: var(--color-text);
  font-weight: 400;
}

.feedback-submitted-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-color: var(--color-surface);
  color: var(--color-sage);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.feedback-submitted-title {
  font-weight: 700;
  color: var(--color-sage);
  margin-bottom: 2px;
}


/* Consent box */

.consent-box {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 20px;
  background-color: var(--color-surface);
  margin-bottom: 20px;
}

.consent-link-row {
  display: flex;
  gap: 10px;
  margin-top: 12px;
}

.consent-link-row input {
  flex: 1;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}

.consent-status-pending {
  color: var(--color-warning);
  font-weight: 600;
}

.consent-status-done {
  color: var(--color-sage);
  font-weight: 600;
}

/* Same min-width: auto flex-overflow trap as the registration
   dropdowns — a long consent URL forces this row wider than its
   container unless the input is explicitly told it can shrink. */
.consent-link-row {
  min-width: 0;
}

.consent-link-row input {
  min-width: 0;
  flex: 1;
}