/* Palette — Yonsei blue on white, black type.
   The ground is pure #fff, never a tinted grey: separation is carried by
   hairline borders and type, not by stacked near-white fills. Only the
   sidebar/secondary fill steps off white, and it steps *cool* (blue-grey),
   never warm. The blue ramp is the feeds score gradient extended; --ui-accent
   is the same #003377 those chips are locked to in tests. */
:root {
  color-scheme: light dark;
  /* Yonsei blue ramp — the one hue this UI is allowed to be. */
  /* blue-50 must stay distinguishable from --ui-surface-2 (#f2f5f9): it is the
     active-nav / chip / callout fill and would vanish inside the sidebar
     otherwise. Held at >=1.15:1 against surface-2 while keeping --ui-faint
     (the weakest text that lands on it) above 4.5:1. Every accent-soft fill in
     the app pairs with an --ui-accent border, never --ui-border-strong, which
     would only reach 2.7:1 on it — keep it that way. */
  --ui-blue-50: #d4e3f4;
  --ui-blue-100: #bfccdd;
  --ui-blue-200: #8099bb;
  --ui-blue-400: #406699;
  --ui-blue-600: #003377;
  --ui-blue-900: #001f49;
  --ui-bg: #ffffff;
  --ui-surface: #ffffff;
  --ui-surface-2: #f2f5f9;
  --ui-surface-raised: #ffffff;
  --ui-border: #dbe2ea;
  /* border-strong is the *component* edge (inputs, popovers, hover, markers).
     With --ui-bg == --ui-surface it is often the only thing identifying a
     control, so it is held at >=3:1 against both white and --ui-surface-2
     (WCAG 1.4.11). --ui-border stays a decorative hairline and is not. */
  --ui-border-strong: #78899f;
  --ui-text: #000000;
  --ui-muted: #45505e;
  --ui-faint: #586477;
  --ui-accent: var(--ui-blue-600);
  --ui-accent-soft: var(--ui-blue-50);
  --ui-accent-text: var(--ui-blue-600);
  --ui-danger: #a4231d;
  --ui-success: #14663c;
  --ui-warning: #7a5300;
  --ui-radius-control: 7px;
  --ui-radius-card: 9px;
  --ui-radius-overlay: 13px;
  --ui-shadow-lg: 0 22px 52px rgba(0, 24, 56, .16);
  --ui-font: Inter, Pretendard, -apple-system, BlinkMacSystemFont, "Segoe UI",
    "Apple SD Gothic Neo", Roboto, Helvetica, Arial, sans-serif;
  --ui-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  --ui-reading: Iowan Old Style, "Noto Serif KR", "AppleMyungjo", Georgia, serif;
  /* Claude Code Docs scale: 16px reading text, 14px navigation/controls,
     12px metadata. Feature CSS may stay denser for plots and data tables. */
  --ui-font-body: 16px;
  --ui-font-ui: 14px;
  --ui-font-meta: 12px;
  /* z-index ladder — overlays must use these, never literals */
  --ui-z-sticky: 30;      /* in-page sticky bars */
  --ui-z-chrome: 60;      /* page chrome (sidebar / topbar) */
  --ui-z-nav-backdrop: 90;
  --ui-z-nav: 103;
  --ui-z-panel-scrim: 120;
  --ui-z-panel: 130;
  --ui-z-toast: 140;
  --ui-z-popover: 145;    /* anchored popovers (may open from a panel) */
  --ui-z-skip: 300;
}

/* Standard breakpoints (media queries cannot read tokens): 680px compact /
   full-screen sheets · 900px shell mobile nav (legacy 899px queries stay) ·
   1280px detail panel docks as inspector. New code uses only these. */

[data-theme="light"] { color-scheme: light; }

/* Dark is the same scheme inverted: neutral blue-grey surfaces, white type,
   and the blue ramp lifted to stay legible on a dark ground. */
[data-theme="dark"] {
  color-scheme: dark;
  --ui-bg: #0c1016;
  --ui-surface: #141a22;
  --ui-surface-2: #1b222c;
  --ui-surface-raised: #19212a;
  --ui-border: #2c3541;
  --ui-border-strong: #626f7d;
  --ui-text: #ffffff;
  --ui-muted: #a7b2c0;
  --ui-faint: #919cac;
  --ui-accent: #7fabe6;
  --ui-accent-soft: #173254;
  --ui-accent-text: #a3c6f0;
  --ui-danger: #f08b84;
  --ui-success: #63c58c;
  --ui-warning: #dcae52;
  --ui-shadow-lg: 0 24px 58px rgba(0, 0, 0, .55);
}

* { box-sizing: border-box; }

html {
  min-width: 320px;
  background: var(--ui-bg);
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  margin: 0;
  background: var(--ui-bg);
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: var(--ui-font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body.portal-nav-open { overflow: hidden; }

button,
input,
textarea,
select { font: inherit; }

button,
a { -webkit-tap-highlight-color: transparent; }

a { color: var(--ui-accent-text); }

img { max-width: 100%; }

::selection { background: var(--ui-accent-soft); }

.skip-link {
  position: fixed;
  z-index: var(--ui-z-skip);
  top: 8px;
  left: 8px;
  padding: 8px 12px;
  border: 1px solid var(--ui-accent);
  border-radius: var(--ui-radius-control);
  background: var(--ui-surface-raised);
  color: var(--ui-text);
  text-decoration: none;
  transform: translateY(-150%);
}

.skip-link:focus { transform: translateY(0); }

/* Visually hidden, screen-reader available (clip pattern — same as studio.css). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  white-space: nowrap;
  border: 0;
  clip-path: inset(50%);
}

/* Authenticated Portal shell */
.portal-shell {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  min-height: 100vh;
}

.top {
  color: var(--ui-text);
  background: var(--ui-surface-2);
  border-color: var(--ui-border);
}

.portal-shell > .top {
  position: sticky;
  z-index: var(--ui-z-chrome);
  top: 0;
  display: flex;
  flex-direction: column;
  align-self: start;
  width: 220px;
  height: 100vh;
  padding: 16px 12px 12px;
  border-right: 1px solid var(--ui-border);
}

.brand-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.brand {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  min-width: 0;
}

.brand > a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  color: var(--ui-text);
  font-size: 14px;
  font-weight: 680;
  letter-spacing: -.01em;
  text-decoration: none;
}

.brand img {
  width: 27px;
  height: 27px;
  border: 1px solid color-mix(in srgb, var(--ui-border) 70%, transparent);
  border-radius: 7px;
}

.portal-nav-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
  margin-top: 24px;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-label {
  margin: 0 9px 6px;
  color: var(--ui-faint);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.nav-label.owner-label {
  margin-top: 20px;
  padding-top: 17px;
  border-top: 1px solid var(--ui-border);
}

.nav a {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 34px;
  padding: 7px 10px;
  border-radius: var(--ui-radius-control);
  color: var(--ui-muted);
  font-size: var(--ui-font-ui);
  font-weight: 560;
  text-decoration: none;
  white-space: nowrap;
}

.nav a::before {
  width: 5px;
  height: 5px;
  margin-right: 10px;
  border: 1px solid var(--ui-border-strong);
  border-radius: 2px;
  content: "";
}

/* The sidebar is --ui-surface-2, so a --ui-surface fill is white-on-near-white
   and carries no state on its own: hover steps to the secondary fill and the
   active row keeps an inset hairline (plus the accent ::before square). */
.nav a:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.nav a.active {
  background: var(--ui-surface);
  box-shadow: inset 0 0 0 1px var(--ui-border);
  color: var(--ui-text);
  font-weight: 680;
}

.nav a.active::before {
  border-color: var(--ui-accent);
  background: var(--ui-accent);
}

.nav a .ext {
  margin-left: 4px;
  font-size: 10px;
  opacity: .6;
}

.top-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.portal-shell .top-right {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--ui-border);
}

.theme-toggle {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: 0;
  padding: 0;
  /* Icon-only and unlabelled: nothing but the edge says "control", so it takes
     the >=3:1 border. Labelled chips keep the decorative --ui-border. */
  border: 1px solid var(--ui-border-strong);
  border-radius: var(--ui-radius-control);
  background: transparent;
  color: var(--ui-muted);
  cursor: pointer;
  line-height: 1;
}

/* The resting border is already --ui-border-strong, so hover escalates past it
   rather than restating it. */
.theme-toggle:hover {
  border-color: var(--ui-text);
  background: var(--ui-surface);
  color: var(--ui-text);
}

.theme-toggle svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

.theme-toggle .ti-sun { display: none; }
.theme-toggle .ti-moon { display: block; }
[data-theme="dark"] .theme-toggle .ti-moon { display: none; }
[data-theme="dark"] .theme-toggle .ti-sun { display: block; }

.nav-toggle,
.nav-backdrop { display: none; }

.portal-main {
  width: min(100%, 1240px);
  min-width: 0;
  margin: 0 auto;
  padding: 34px clamp(24px, 4vw, 52px) 64px;
}

.portal-main:focus { outline: none; }

h1,
h2,
h3 {
  color: var(--ui-text);
  line-height: 1.25;
}

h1 {
  margin: 0 0 8px;
  font-size: 30px;
  font-weight: 720;
  letter-spacing: -.025em;
}

h2 { font-size: 22px; }

.muted { color: var(--ui-muted); }

/* The one back-link (page header "← Parent" affordance) shared by every page. */
.page-back {
  color: var(--ui-muted);
  font-size: var(--ui-font-ui);
  text-decoration: none;
}

.page-back:hover {
  color: var(--ui-accent-text);
  text-decoration: underline;
}

/* Shared empty-state: dashed slot, muted, centered (models the
   docs-empty/feeds-empty/proj-empty family). Pages layer it on their local
   empty class; new surfaces use it alone. */
.empty-state {
  padding: 20px 16px;
  border: 1px dashed var(--ui-border);
  border-radius: var(--ui-radius-card);
  color: var(--ui-muted);
  text-align: center;
}

/* Public compact shell */
.public-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.public-top {
  position: sticky;
  z-index: 50;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 56px;
  padding: 10px clamp(18px, 4vw, 34px);
  border-bottom: 1px solid var(--ui-border);
  background: color-mix(in srgb, var(--ui-surface) 92%, transparent);
  backdrop-filter: blur(12px);
}

.public-top .brand {
  flex-wrap: nowrap;
  gap: 12px;
}

.feeds-signin {
  padding: 6px 9px;
  border-radius: var(--ui-radius-control);
  color: var(--ui-muted);
  font-size: var(--ui-font-ui);
  text-decoration: none;
}

.feeds-signin:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.public-page main {
  width: 100%;
  padding: 30px clamp(20px, 4vw, 48px) 64px;
}

/* Login */
.login {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  background:
    radial-gradient(circle at 15% 10%, var(--ui-accent-soft), transparent 30rem),
    var(--ui-bg);
}

.login .box {
  width: min(100%, 390px);
  padding: 42px 34px 36px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-overlay);
  background: var(--ui-surface);
  text-align: center;
}

.login img {
  width: 68px;
  height: 68px;
  margin-bottom: 17px;
  border: 1px solid var(--ui-border);
  border-radius: 14px;
}

.login h1 {
  margin-bottom: 28px;
  font-size: 30px;
}

.gh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 42px;
  padding: 9px 18px;
  border: 1px solid var(--ui-text);
  border-radius: var(--ui-radius-control);
  background: var(--ui-text);
  color: var(--ui-bg);
  font-weight: 650;
  text-decoration: none;
}

.gh-btn:hover { opacity: .86; }

.gh-btn svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

.login .footer {
  margin-top: 25px;
  color: var(--ui-faint);
  font-size: 13px;
}

/* Portal-native auth forms (login / register) share the .login box. */
.login .auth-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
}

.login .auth-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--ui-font-ui);
  color: var(--ui-faint);
}

.login .auth-form input {
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid var(--ui-border-strong);
  border-radius: var(--ui-radius-control);
  background: var(--ui-surface);
  color: var(--ui-text);
  font-size: var(--ui-font-body);
}

.login .auth-form p { margin: 0; }

.login .form-error {
  color: var(--ui-danger);
  font-size: var(--ui-font-ui);
}

.login .auth-hint {
  color: var(--ui-faint);
  font-size: var(--ui-font-ui);
}

/* Branded error pages (core.errors) reuse the .login box. */
.login .error-title {
  margin: 0;
  font-size: 15px;
  font-weight: 650;
}

/* Common controls and accessibility */
/* A field's fill now matches the page, so its edge is the whole affordance — it
   gets the >=3:1 component border, not the decorative hairline, and states the
   full shorthand so an engine that suppresses the UA border (Safari
   `appearance: textfield`) cannot leave the field edgeless. */
:where(input[type="search"], input[type="text"], textarea, select) {
  border: 1px solid var(--ui-border-strong);
  background: var(--ui-surface);
  color: var(--ui-text);
}

:where(input, textarea)::placeholder { color: var(--ui-faint); }

:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: 2px;
  border-radius: 3px;
}

@media (pointer: coarse) {
  .theme-toggle,
  .nav-toggle { min-width: 44px; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }
}

@media (max-width: 899px) {
  .portal-shell {
    display: block;
    min-height: 100vh;
  }

  .portal-shell > .top {
    position: sticky;
    top: 0;
    display: block;
    width: 100%;
    height: 56px;
    padding: 10px 14px;
    border-right: 0;
    border-bottom: 1px solid var(--ui-border);
    background: color-mix(in srgb, var(--ui-surface) 94%, transparent);
    backdrop-filter: blur(12px);
  }

  .brand-row {
    position: relative;
    z-index: calc(var(--ui-z-nav) + 1);
    align-items: center;
  }

  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 36px;
    height: 36px;
    padding: 0;
    /* Icon-only — see .theme-toggle. */
    border: 1px solid var(--ui-border-strong);
    border-radius: var(--ui-radius-control);
    background: var(--ui-surface);
    color: var(--ui-text);
    cursor: pointer;
  }

  .nav-toggle span {
    width: 15px;
    height: 1.5px;
    border-radius: 2px;
    background: currentColor;
    transition: transform .14s ease, opacity .14s ease;
  }

  .portal-nav-open .nav-toggle span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
  .portal-nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
  .portal-nav-open .nav-toggle span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

  .portal-nav-body {
    position: fixed;
    z-index: var(--ui-z-nav);
    inset: 0 auto 0 0;
    display: flex;
    width: min(320px, 86vw);
    height: 100dvh;
    margin: 0;
    padding: 82px 16px 16px;
    border-right: 1px solid var(--ui-border);
    background: var(--ui-surface);
    box-shadow: var(--ui-shadow-lg);
    transform: translateX(-105%);
    transition: transform .18s ease;
  }

  .portal-nav-open .portal-nav-body { transform: translateX(0); }

  .portal-shell .top-right { padding: 16px 2px 0; }

  .nav-backdrop {
    position: fixed;
    z-index: var(--ui-z-nav-backdrop);
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: rgba(0, 16, 38, .45);
    cursor: default;
  }

  .portal-nav-open .nav-backdrop { display: block; }

  .portal-main {
    width: 100%;
    padding: 26px 18px 54px;
  }
}

@media (max-width: 520px) {
  .public-page main { padding: 24px 16px 48px; }
  .login .box { padding: 34px 24px 30px; }
}

/* Print: content only — chrome, toolbars, and overlays are screen furniture. */
@media print {
  .skip-link,
  .theme-toggle,
  .nav-toggle,
  .nav-backdrop,
  .portal-shell > .top,
  .public-top,
  .lv-bar { display: none !important; }

  .portal-shell { display: block; min-height: 0; }

  .portal-main {
    width: 100%;
    padding: 0;
  }

  body {
    background: #fff;
    color: #000;
  }
}
