/* ============================================================
   DuctusMed Design System — app.css
   Bu dosya internal/assets/static/app.css'in YERİNE konulacak.
   Mevcut class isimleri (.card, .btn, .alert, .badge vb.) korundu —
   hiçbir Go template değişikliği gerektirmez.
   ============================================================ */

/* Token files used to be pulled in via @import here, which forces the
   browser to download and parse app.css before it can even discover that
   these need fetching too — a Lighthouse trace's NetworkDependencyTree
   insight flagged the resulting chain as extending the critical path.
   Every page that links app.css (base.html, account-base.html) now links
   these four directly instead, in parallel with app.css rather than
   after it — see either file's own comment on the change. */

/* Base reset and typography */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Was a flat 1100px, which on any normal desktop screen left roughly 400px
     of empty page either side of every page on the site. Fluid instead: wide
     screens get room, and 94vw keeps a margin at every size below that so
     content never touches the glass. */
  --container: min(1500px, 94vw);
  --nav-h: 64px;
}

html { font-size: 16px; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-sans);
  color: var(--color-text);
  background: var(--color-surface);
  line-height: 1.6;
}

/* Container */
.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--space-4); }

/* ── Nav ── */
.site-nav {
  height: var(--nav-h);
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  padding: 0 var(--space-6);
  gap: var(--space-6);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: none;
}
/* :not(.btn) matters: base.html's nav CTAs ("Giriş Yap"/"Ücretsiz Dene") are
   plain <a class="btn btn-sm">/<a class="btn btn-outline btn-sm"> links
   (correctly reusing the shared Button styling per that file's own comment,
   rather than one-off nav buttons) sitting directly inside .site-nav. Without
   this exclusion, this rule's element+class selector (.site-nav a) is more
   specific than .btn/.btn-outline/.btn-sm's single class each, so it silently
   overrode their color/weight/size/padding — the two most important CTAs on
   every page rendered in muted gray at nav-link weight instead of the
   button's actual brand-indigo styling.
   :not(.n-logo) matters too: .n-logo (base.html) is the actual, complete,
   modern styling for the wordmark link — this rule's .site-nav a:first-child
   counterpart (deleted below) was a leftover from before .n-logo existed,
   and its higher specificity (element+class vs .n-logo's single class) was
   silently overriding .n-logo's color, making "Ductus" render the same
   indigo as the "Med" span instead of the intended two-tone.
   :not(.n-links a) matters for the same reason, found the hard way: an
   earlier version of this comment claimed .n-links a (base.html) "already
   fully supersedes this rule" without checking the actual specificity —
   :not(.btn):not(.n-logo) alone is (0,3,1), which beats .n-links a[aria-
   current="page"]'s (0,2,1) and plain .n-links a's (0,1,1) outright, so
   every center nav link (active or not) was silently losing its intended
   color/weight/size/padding to this rule, the identical bug class as the
   .btn and .n-logo cases above — just not caught until a review measured
   the computed styles instead of trusting the comment. */
.site-nav a:not(.btn):not(.n-logo):not(.n-links a) {
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: .875rem;
  font-weight: var(--fw-medium);
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
  border-radius: 9px;
  transition: color .2s, background .2s;
}
.site-nav a:hover:not(.btn):not(.n-logo):not(.n-links a) { color: var(--color-text); background: var(--color-surface); text-decoration: none; }
.site-nav .nav-spacer { flex: 1; }
.site-nav form { display: inline; }
.site-nav button {
  background: none;
  border: 1.5px solid var(--color-border);
  color: var(--color-text-muted);
  padding: .4rem .9rem;
  border-radius: 9px;
  cursor: pointer;
  font-size: .85rem;
  font-family: inherit;
  transition: border-color .2s, color .2s, background .2s;
}
.site-nav button:hover { border-color: var(--color-primary); color: var(--color-primary); background: var(--color-primary-soft); }

/* Main layout */
main { padding: var(--space-8) var(--space-6); min-height: calc(100vh - var(--nav-h)); }

/* Typography */
h1 { font-family: var(--font-display); font-size: 2rem; font-weight: var(--fw-regular); letter-spacing: -.02em; margin-bottom: var(--space-4); color: var(--color-text); }
h2 { font-family: var(--font-display); font-size: 1.5rem; font-weight: var(--fw-regular); margin: var(--space-6) 0 var(--space-3); color: var(--color-text); }
h3 { font-size: 1.05rem; font-weight: var(--fw-bold); margin: var(--space-5) 0 var(--space-2); color: var(--color-text); }
p { margin-bottom: var(--space-3); }
a { color: var(--color-link); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Forms ── */
form { max-width: 480px; }
label {
  display: block;
  font-size: .8rem;
  font-weight: var(--fw-bold);
  color: var(--color-text-muted);
  margin-bottom: .375rem;
  margin-top: var(--space-4);
}
label:first-of-type { margin-top: 0; }
input[type=text],
input[type=email],
input[type=password],
input[type=number],
input[type=date],
input[type=tel],
select,
textarea {
  display: block;
  width: 100%;
  padding: .65rem .9rem;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius);
  font-size: .95rem;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-surface-card);
  transition: border-color .2s, box-shadow .2s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(79,70,229,.1);
}
/* accent-color: without it every checkbox on the site (including
   component-checkbox's) checks in the browser's own default blue instead of
   the app's indigo brand color — the one native form control CSS can theme
   directly, so there's no reason it should be the one left unbranded. */
input[type=checkbox] { width: auto; margin-right: .4rem; accent-color: var(--color-primary); }
/* input[type=file] ships with the OS's own unthemed control (a gray
   "Choose File" button on light and dark alike) — every other input on this
   page picks up the shared surface/border tokens above, but the browser
   default here sat as a stark light-mode-only button on account-profile.html's
   dark card. Restyle only the shown ::file-selector-button (the actual
   clickable control); the filename text after it is native chrome that
   isn't stylable and inherits color from the input itself. */
input[type=file] {
  display: block;
  width: 100%;
  padding: .3rem 0;
  font-size: .85rem;
  font-family: inherit;
  color: var(--color-text-muted);
}
input[type=file]::file-selector-button {
  font-family: inherit;
  font-size: .85rem;
  font-weight: var(--fw-semibold);
  padding: .5rem 1rem;
  margin-right: .75rem;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-card);
  color: var(--color-text);
  cursor: pointer;
  transition: background .2s, border-color .2s, color .2s;
}
input[type=file]::file-selector-button:hover {
  background: var(--color-surface);
  border-color: var(--color-primary);
  color: var(--color-primary);
}
textarea { resize: vertical; min-height: 80px; }
input.invalid, select.invalid, textarea.invalid { border-color: var(--color-danger); }
/* Promoted from account-address-form.html's page-local .af-hint/.af-field-err
   (the only page with a real per-field error state before component-input
   existed) so the shared component can use them anywhere, not just inside
   that page's own .af wrapper. */
.field-hint { color: var(--color-text-muted); font-size: .8rem; margin-top: .2rem; }
.field-err { color: var(--color-danger); font-size: .82rem; margin-top: .25rem; }
/* .field-check: the shared checkbox-field wrapper (component-checkbox) —
   promoted from sign-up.html's page-local .n-auth-check (ductusmed-theme.css),
   the only page with this layout before component-checkbox existed. */
.field-check { display: flex; align-items: flex-start; gap: .55rem; font-size: .88rem; color: var(--color-text-muted); line-height: 1.4; margin-bottom: var(--space-4); }
.field-check input[type=checkbox] { margin: .15rem 0 0; flex-shrink: 0; }
.field-check.invalid input[type=checkbox] { outline: 2px solid var(--color-danger); outline-offset: 2px; }
/* A consent link (KVKK aydınlatma metni, checkout's §7.8 waiver) inside this
   muted-gray label text measured 1.24:1 against it (axe/Lighthouse,
   link-in-text-block) -- no --color-link tuning survives being checked
   against --color-text-muted specifically (it's tuned for normal body text
   and surfaces, a brighter baseline than this already-dim label). An
   underline sidesteps the color-contrast race entirely, which is also the
   more expected treatment for a legal-document link anyway. */
.field-check a { text-decoration: underline; }

/* ── Buttons ── */
button, .btn {
  display: inline-block;
  padding: .65rem 1.375rem;
  border-radius: 10px;
  border: none;
  font-size: .9rem;
  font-weight: var(--fw-bold);
  font-family: inherit;
  cursor: pointer;
  text-decoration: none;
  transition: background .2s, transform .2s, box-shadow .2s;
  background: var(--color-primary);
  color: var(--white);
  box-shadow: 0 2px 8px rgba(79,70,229,.25);
}
button:hover, .btn:hover { background: var(--color-primary-d); text-decoration: none; transform: translateY(-1px); box-shadow: 0 4px 14px rgba(79,70,229,.32); }
button:active, .btn:active { transform: translateY(0); }
/* Previously no disabled state existed at all: a disabled button (e.g.
   sign-in's "Gönderiliyor…" submit-lock) rendered pixel-identical to an
   active one, the only sign anything changed being the label text. Dimming
   + cursor + suppressing the hover lift/shadow gives the disabled state a
   visual signal, and pointer-events:none stops :hover's transition from
   firing at all rather than relying on every :hover rule to also guard
   against :disabled. */
button:disabled, .btn:disabled {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
  pointer-events: none;
}
button[type=submit] { margin-top: var(--space-5); }
.btn-sm { padding: .4rem .85rem; font-size: .82rem; box-shadow: none; }
/* Extra-small pill action, for compact inline list rows (topic cards, blind-
   spot rows). Was hand-rolled separately in tus-map.html (.pbtn) and
   dashboard.html (.ks-btn) with near-identical values. */
.btn-xs {
  display: inline-block; padding: .35rem .7rem; border-radius: 7px;
  font-size: .72rem; font-weight: var(--fw-semibold); box-shadow: none;
  white-space: nowrap; text-decoration: none; flex-shrink: 0;
  background: var(--color-primary-d); color: var(--white);
  transition: background .15s;
}
.btn-xs:hover { background: var(--color-primary); }
/* color/border-color: var(--color-link), not --color-primary: transparent
   background means the effective background is whatever surface sits
   behind it -- account-profile.html's "Şifreyi Değiştir" button (this
   variant) measured 3.83:1 on its card's dark background in dark mode
   (axe/Lighthouse). --color-link carries the dark-mode-appropriate
   lighter shade (unchanged in light mode, where it still equals
   --color-primary) and clears AA on the dark surfaces checked. */
.btn-outline {
  background: transparent;
  color: var(--color-link);
  border: 1.5px solid var(--color-link);
  box-shadow: none;
}
.btn-outline:hover { background: var(--color-primary-soft); color: var(--color-link); transform: none; box-shadow: none; }
.btn-secondary { background: var(--color-surface); color: var(--color-text); border: 1.5px solid var(--color-border); box-shadow: none; }
.btn-secondary:hover { background: var(--color-surface-card); border-color: var(--color-primary); color: var(--color-primary); transform: none; box-shadow: none; }
.btn-danger { background: var(--color-danger-solid); box-shadow: 0 2px 8px rgba(239,68,68,.25); }
.btn-danger:hover { background: var(--color-danger-solid-d); }
/* Nav WhatsApp CTA (base.html's .n-r) — icon + label, so inline-flex/gap
   rather than .btn's plain inline-block like the other nav buttons. */
/* box-shadow intentionally omitted: .btn-whatsapp's only call site
   (contact.html) always pairs it with .btn-sm, which already sets
   box-shadow: none -- an earlier version set one here too, and because
   both are single-class selectors, this rule's later position in the
   cascade silently overrode .btn-sm's, leaving the WhatsApp pill as the
   only nav/footer button on the site carrying a drop shadow. */
.btn-whatsapp { display: inline-flex; align-items: center; gap: .4rem; background: var(--color-whatsapp-solid); }
.btn-whatsapp:hover { background: var(--color-whatsapp-solid-d); }
/* Mail counterpart to .btn-whatsapp -- same shape, --color-primary-d fill.
   Reused by the footer contact line (contact_footer) so it shares
   .btn/.btn-sm's hover/focus/text-decoration handling instead of re-deriving
   its own pill rule. --color-primary-d rather than --color-primary: white
   text on --color-primary computes 4.467:1, just under WCAG AA's 4.5:1 for
   normal-weight text at this size; --color-primary-d clears it at 6.288:1,
   matching the existing --color-primary-d-as-small-text-fill precedent in
   .btn-xs above. */
.btn-mail { display: inline-flex; align-items: center; gap: .4rem; background: var(--color-primary-d); }
.btn-mail:hover { background: var(--color-primary); }
/* White-on-brand-background CTA (used on the hero gradient / colored cards).
   Was hand-rolled separately in how-it-works.html (.nc-btn-cta) and
   dashboard.html (.dash-start-btn) with near-identical values; this is the
   single shared definition both now use. */
.btn-inverse {
  background: var(--white); color: var(--color-primary); font-weight: var(--fw-extrabold);
  font-size: .92rem; padding: .85rem 1.875rem; box-shadow: 0 4px 16px rgba(0,0,0,.15);
}
.btn-inverse:hover { background: var(--white); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,.2); }

/* .ip-btn — instructor-base.html's compact secondary button, also reused by a
   few plain-"base" pages (account-addresses, account-address-form, book-detail)
   that don't extend instructor-base.html and so never had the class itself. */
.ip-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .85rem; font-weight: var(--fw-semibold); padding: .55rem var(--space-4); border-radius: 10px;
  border: 1.5px solid var(--color-border); color: var(--color-text); background: var(--color-surface-card);
  white-space: nowrap; text-decoration: none; cursor: pointer; font-family: inherit;
}
.ip-btn:hover { border-color: #C7D2FE; color: var(--color-primary); }
.ip-btn.primary { background: var(--color-primary); color: var(--white); border-color: var(--color-primary); }
.ip-btn.primary:hover { background: var(--color-primary-d); color: var(--white); }

/* ── Tables ── */
table { width: 100%; border-collapse: collapse; font-size: .88rem; }
th, td { padding: .7rem .9rem; text-align: left; border-bottom: 1px solid var(--color-border); }
th { font-weight: var(--fw-bold); background: var(--color-surface); font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--color-text-muted); }
tr:hover td { background: var(--color-surface); }
table code { font-size: .85em; background: var(--color-primary-soft); color: var(--color-primary); padding: .1em .35em; border-radius: 4px; }

/* ── Cards ── */
.card {
  background: var(--color-surface-card);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1.375rem var(--space-6);
  box-shadow: var(--shadow);
  margin-bottom: var(--space-5);
  display: flex;
  flex-direction: column;
  transition: border-color .2s, box-shadow .2s;
}
.card:hover { border-color: rgba(79,70,229,.2); }
.card h3 { margin-top: 0; }
.card p { flex: 1; color: var(--color-text-muted); font-size: .9rem; }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-5);
}

/* ── Stats ── */
.stats-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}
/* .stat-card/.stat-card::before/.stat-label were removed with issue #211:
   every page that used them is on .stat-tile (component-card) now, and they
   had zero template consumers left. .stat-value survives because
   course-detail.html:111 still uses it standalone, for a price, outside any
   stat tile. */
.stat-value {
  display: block;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: var(--fw-regular);
  color: var(--color-primary);
  line-height: 1;
}

/* ── Alerts / status ── */
.alert {
  padding: .85rem 1.125rem;
  border-radius: var(--radius);
  margin-bottom: var(--space-4);
  font-size: .88rem;
  border: 1.5px solid transparent;
}
.alert-success { background: var(--color-success-soft); color: var(--color-success-ink); border-color: var(--color-success-border); }
.alert-error { background: var(--color-danger-soft); color: var(--color-danger); border-color: var(--color-danger-border); }
.alert-warn { background: var(--color-warning-soft); color: var(--color-warning-ink); border-color: var(--color-warning-border); }
.alert-info { background: var(--color-primary-soft); color: var(--color-primary-ink); border-color: rgba(79,70,229,.2); }
/* An alert nested inside a .card (course-detail.html's "Kayıtlısınız" box,
   e.g.) had its <p>'s color silently taken over by .card p's own
   color: var(--color-text-muted) rule -- inheritance from .alert-success
   etc. above has no specificity at all, so any matching rule beats it
   regardless of how unrelated its intent is. Measured 4.36:1 (axe/
   Lighthouse) where the alert's own ink color (--color-success-ink here)
   would have cleared AA easily. Same specificity as .card p (one class +
   one element); this only wins because it's declared later. */
.alert p { color: inherit; }
.error { color: var(--color-danger); font-size: .88rem; margin: var(--space-2) 0; }

/* ── Brand mark ──
   The "DuctusMed" wordmark as a solid chip (dark fill + light "Ductus" +
   indigo "Med", or the inverse) rather than bare two-tone text sitting
   directly on whatever background happens to be behind it. Previously three
   separate copies (base.html's .n-logo, sign-in.html's .auth-logo,
   instructor-base.html's .ip-logo) each hand-rolled their own two-tone text
   color pair with no chip/background at all. Consolidated here as the one
   visual definition for pages that link this file — .n-logo/.auth-logo now
   only handle each context's outer layout (flex placement, margins).
   instructor-base.html is the one exception: it deliberately never links
   app.css (a standalone shell, only the token files), so .ip-logo duplicates
   this block verbatim rather than sharing it — keep the two in sync.
   font-size is deliberately not set here — every placement sets its own on
   the wrapper, and padding/border-radius scale with it via em units. */
.brand-mark {
  display: inline-flex;
  align-items: center;
  gap: 0;
  font-weight: var(--fw-extrabold);
  letter-spacing: -.02em;
  line-height: 1.2;
  padding: .35em .6em;
  border-radius: .55em;
  background: var(--color-text);
  color: var(--color-bg);
}
/* --color-primary on the chip's own background (--color-text, not
   --color-bg -- .brand-mark is a deliberate full inversion of the page's
   own text/bg pair) measured 4.46:1 in light mode (axe/Lighthouse), just
   under the 4.5:1 AA minimum. A first attempt switched this to the
   theme-aware --color-primary-ink, but that token is meant for text on
   --color-bg, the *opposite* of what this chip's background does as the
   theme flips -- it measured worse in dark mode (2.46:1: dark mode's
   light ink shade landing on dark mode's now-light --color-text chip).
   --color-primary-chip-ink carries the correctly-inverted mapping (see
   its definition in color-tokens.css) and clears AA in both themes. */
.brand-mark .brand-med { color: var(--color-primary-chip-ink); }
/* Forces the inverse (light chip, dark "Ductus") regardless of the site
   theme toggle — for chrome whose surrounding background is always dark
   independent of that toggle, e.g. the instructor sidebar (see
   instructor-base.html: "the sidebar is already this same dark navy in
   light mode"). Without this, .brand-mark's default (keyed to --color-text/
   --color-bg, which follow the site theme) would render a dark-on-light
   chip *design* correctly for a light-themed page, but the sidebar's own
   background is dark in both themes — a dark chip there would nearly
   vanish. Both colors here are deliberately theme-stable literals/scale
   tokens (--white, --slate-900), not --color-bg/--color-text: those two
   flip with the site theme, which is exactly the bug this rule exists to
   route around — in dark theme they'd resolve to near-white bg + near-white
   text, erasing "Ductus" on its own chip. */
.brand-mark--on-dark { background: var(--white); color: var(--slate-900); }
/* .brand-mark .brand-med (above) uses the theme-aware --color-primary-chip-ink,
   correct when the chip's own background follows the site theme -- but this
   modifier forces a theme-stable white background (comment above), so it
   needs a theme-stable ink color too. Same fix as --slate-900 above: a
   literal that doesn't flip underneath a background that doesn't either. */
.brand-mark--on-dark .brand-med { color: var(--color-primary-d); }

/* ── Badges ── */
.badge {
  display: inline-block;
  padding: .25em .65em;
  border-radius: 99px;
  font-size: .72rem;
  font-weight: var(--fw-bold);
}
.badge-green { background: var(--color-success-soft); color: var(--color-success); }
.badge-red { background: var(--color-danger-soft); color: var(--color-danger); }
.badge-yellow { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-gray { background: var(--color-surface); color: var(--color-text-muted); }
/* Semantic aliases, matching .alert-*'s naming (success/warn/danger/info)
   rather than the color names above. Added because admin-cms.html and
   admin-users.html already used "badge-success"/"badge-warn" — presumably
   assuming badges followed the same semantic convention alerts do — and
   neither was ever actually defined anywhere, so those badges rendered
   with no color at all. The color-named classes above stay: several pages
   already use them correctly and renaming would be pure churn; new callers
   should reach for these semantic ones (or component-badge) instead. */
.badge-success { background: var(--color-success-soft); color: var(--color-success); }
.badge-warn { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-danger { background: var(--color-danger-soft); color: var(--color-danger); }
.badge-info { background: var(--color-primary-soft); color: var(--color-primary-ink); }

/* ── Stat tile (component-card) ──
   A bordered number+caption tile — the shape five pages independently
   hand-rolled (instructor-base.html's .ip-kpi, admin-users.html's and
   course-edit.html's .stat-card, account-courses.html's .ac-stat,
   admin-content-health.html's .n-stat, admin-mcq-queue.html's .stat/.n/.l),
   all of them now migrated here with their own rules deleted.
   admin-users.html's copy used --slate-200 for its border — a theme-stable
   token never redefined for dark mode — so its tiles rendered with a
   bright light-gray border that stood out against every other (properly
   theme-aware, var(--color-border)) border on the same dark page. */
.stat-tile { background: var(--color-surface-card); border: 1.5px solid var(--color-border); border-radius: var(--radius-lg); padding: 1.1rem 1.4rem; display: inline-block; min-width: 150px; }
.stat-tile-value { display: block; font-family: var(--font-display); font-size: 1.9rem; line-height: 1; color: var(--color-text); }
.stat-tile-label { display: block; font-size: .78rem; color: var(--color-text-muted); margin-top: .35rem; }
.stat-tile-amber { background: var(--color-warning-soft); border-color: var(--color-warning-border); }
.stat-tile-amber .stat-tile-value { color: var(--color-warning-ink); }
.stat-tile-red .stat-tile-value { color: var(--color-danger); }
.stat-tile-green .stat-tile-value { color: var(--color-success); }
.stat-tile-primary { background: linear-gradient(135deg, var(--color-primary-soft), var(--color-surface-card)); border-color: var(--color-primary-soft); }
.stat-tile-icon { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; margin-bottom: .5rem; border-radius: var(--radius-sm); background: var(--color-primary-soft); color: var(--color-primary); font-size: 1.05rem; line-height: 1; }
.stat-tile-amber .stat-tile-icon { background: var(--color-warning-border); color: var(--color-warning-ink); }

/* ── Progress bar ── */
.progress { height: 8px; background: var(--color-surface); border-radius: 99px; overflow: hidden; border: 1px solid var(--color-border); }
.progress-bar { height: 100%; background: linear-gradient(90deg, var(--color-primary), var(--color-primary-l)); border-radius: 99px; transition: width .5s cubic-bezier(.4,0,.2,1); }

/* ── Player wrapper (video sistemi — dokunulmadı) ── */
#player-wrapper { border-radius: var(--radius); overflow: hidden; background: #000; box-shadow: var(--shadow); }
#player-frame { aspect-ratio: 16/9; }
.player-loading {
  position: absolute; inset: 0; z-index: 15;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3);
  background: linear-gradient(rgba(10,12,16,.72), rgba(10,12,16,.78));
  color: var(--white); text-align: center;
}
.player-loading-spinner {
  width: 2.5rem; height: 2.5rem; border-radius: 999px;
  border: 3px solid rgba(255,255,255,.25); border-top-color: var(--white);
  animation: player-spin .9s linear infinite;
}
.player-loading-text { margin: 0; font-size: .92rem; font-weight: var(--fw-semibold); letter-spacing: .01em; }
/* Turnstile-load / playback / phone-verification-required overlays inside
   #player-frame — third verbatim copy of this inline style is where it
   becomes a class (assessment 0132 M6). */
.player-overlay-msg { display: none; color: var(--white); padding: 1.5em; text-align: center; margin: 0; }
.player-theater-toggle {
  position: absolute; top: .75rem; right: .75rem; z-index: 20;
  border: 1px solid rgba(255,255,255,.28); background: rgba(17,24,39,.82); color: var(--white);
  padding: var(--space-2) var(--space-3); border-radius: 999px; font-size: .82rem; font-weight: var(--fw-semibold); backdrop-filter: blur(10px);
}
.player-theater-toggle:hover { background: rgba(31,41,55,.92); }
body.player-theater-open { overflow: hidden; }
#player-wrapper.player-wrapper-theater {
  position: fixed !important; inset: 0 !important; width: 100vw !important; height: 100dvh !important;
  padding-bottom: 0 !important; border-radius: 0 !important; box-shadow: none !important; z-index: 9999;
}
#player-wrapper.player-wrapper-theater #player-frame { position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important; aspect-ratio: auto !important; }
#player-wrapper.player-wrapper-theater iframe,
#player-wrapper.player-wrapper-theater video { width: 100% !important; height: 100% !important; }
@keyframes player-spin { to { transform: rotate(360deg); } }

/* ── Breadcrumb ── */
.breadcrumb { font-size: .85rem; color: var(--color-text-muted); margin-bottom: var(--space-5); }
.breadcrumb a { color: var(--color-text-muted); }
.breadcrumb a:hover { color: var(--color-primary); }
.breadcrumb span::before { content: " / "; }
/* Centers the crumb line inside a hero/header section (catalog, faq). */
.breadcrumb-center { display: flex; align-items: center; justify-content: center; gap: var(--space-2); }

/* Account-section breadcrumb (Hesabım › X) — shared by account/orders/checkout
   pages, previously duplicated per-page as .ac-bc / .or-bc / .co-crumb with
   identical rules. */
.acct-crumb { font-size: .85rem; color: var(--color-text-muted); margin-bottom: var(--space-2); }
.acct-crumb a { color: var(--color-text-muted); text-decoration: none; }
.acct-crumb a:hover { color: var(--color-primary); }

/* Bolded current-page segment, used by breadcrumb variants whose markup ends
   in <b>...</b> instead of the .breadcrumb span::before separator style. */
.breadcrumb b, .acct-crumb b { color: var(--color-text); font-weight: var(--fw-semibold); }

/* Account-section empty-state card (account-courses.html / orders.html),
   previously duplicated per-page as .ac-empty / .or-empty with identical rules. */
.acct-empty { background: var(--color-primary-light); border: 1px solid #dfe0ff; border-radius: var(--radius-lg); padding: var(--space-10) var(--space-8); text-align: center; }
.acct-empty h2 { font-family: var(--font-display); margin: .2rem 0 .4rem; }
.acct-empty p { color: var(--color-text-muted); margin: .2rem 0 var(--space-4); }

/* ── Admin nav strip ── */
.admin-nav { display: flex; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-6); font-size: .85rem; padding-bottom: var(--space-4); border-bottom: 1px solid var(--color-border); }
.admin-nav a { color: var(--color-text-muted); font-weight: var(--fw-medium); }
.admin-nav a:hover { color: var(--color-primary); }

/* ── Utilities ── */
.text-muted { color: var(--color-text-muted); font-size: .88rem; }
/* Small uppercase eyebrow label above a section heading (catalog.html's
   "Online Dersler", course-detail.html's "Şeffaf İçerik Planı"). Same
   treatment home.html's own .lp-section-label uses — those two pages wrote
   class="section-label" without ever having a rule for it, so the eyebrow
   rendered as plain unstyled body text with no visual hierarchy above the
   heading it introduces. */
.section-label { font-size: .84rem; font-weight: var(--fw-extrabold); letter-spacing: .12em; text-transform: uppercase; color: var(--color-primary); margin-bottom: .6rem; }
/* Visually hidden but still announced by screen readers — for content
   (fieldset legends, form labels) that's redundant on screen but is the
   only accessible name assistive tech gets. Not display:none/hidden,
   which remove it from the accessibility tree too. */
.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; }

/* ── Details / Summary (eski flashcard aç-kapa — Alpine.js'e geçişte kaldırılacak) ── */
details {
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius);
  padding: .625rem 1.125rem;
  margin-bottom: var(--space-3);
  background: var(--color-surface-card);
}
summary {
  cursor: pointer;
  font-weight: var(--fw-bold);
  padding: var(--space-1) 0;
  list-style: none;
  color: var(--color-primary);
}
summary::-webkit-details-marker { display: none; }
summary::before {
  content: "▸";
  margin-right: var(--space-2);
  color: var(--color-text-muted);
  display: inline-block;
  transition: transform .2s;
}
details[open] > summary::before { transform: rotate(90deg); }

.text-success { color: var(--color-success); }
.text-danger { color: var(--color-danger); }
.text-center { text-align: center; }
.mt-1 { margin-top: var(--space-2); }
.mt-2 { margin-top: var(--space-4); }
.mt-3 { margin-top: var(--space-6); }
.mt-4 { margin-top: var(--space-8); }
.mb-1 { margin-bottom: var(--space-2); }
.mb-2 { margin-bottom: var(--space-4); }
.mb-3 { margin-bottom: var(--space-6); }
.flex { display: flex; }
.items-center { align-items: center; }
.gap-1 { gap: var(--space-2); }
.gap-2 { gap: var(--space-4); }
.w-full { width: 100%; }
code { font-family: var(--font-mono); font-size: .88em; background: var(--color-primary-soft); color: var(--color-primary-d); padding: .15em .4em; border-radius: 4px; }
pre { background: var(--color-surface); padding: var(--space-4); border-radius: var(--radius); overflow-x: auto; font-size: .88rem; border: 1px solid var(--color-border); }

/* ============================================================
   YENİ COMPONENT'LER — DuctusMed tasarım dosyalarından
   (flashcards-study.html'in Alpine.js'e taşınması için gerekli)
   ============================================================ */

/* 3D Flip Card (Unutma Radarı) */
.card-3d-scene { width: 100%; max-width: 560px; margin: 0 auto; perspective: 1200px; cursor: pointer; }
.card-3d { width: 100%; min-height: 280px; position: relative; transform-style: preserve-3d; transition: transform .6s cubic-bezier(.4,0,.2,1); }
.card-3d.is-flipped { transform: rotateY(180deg); }
.card-3d-face { position: absolute; inset: 0; backface-visibility: hidden; border-radius: var(--radius-lg); }
.card-3d-back { transform: rotateY(180deg); }
.card-3d-inner-front {
  background: var(--color-surface-card); border: 1.5px solid var(--color-border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); padding: var(--space-8) 2.25rem; min-height: 280px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
}
.card-3d-inner-back {
  background: linear-gradient(160deg, #F0F9FF, var(--color-primary-soft));
  border: 1.5px solid rgba(79,70,229,.2); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); padding: 1.75rem 2.25rem; min-height: 280px;
  display: flex; flex-direction: column;
}
.flashcard-question { font-family: var(--font-display); font-size: 1.3rem; line-height: 1.5; margin: var(--space-4) 0; }
.flashcard-answer { font-family: var(--font-display); font-size: 1.15rem; line-height: 1.6; padding: var(--space-4) 0; }
.flashcard-trap {
  background: linear-gradient(135deg,var(--color-warning-soft),#FFF7ED); border: 1.5px solid var(--color-warning-border);
  border-radius: var(--radius); padding: .875rem 1.125rem; font-size: .85rem; color: var(--color-warning-ink); margin-top: var(--space-3);
}

/* Rating buttons (Zorlandım / Hatırladım / Çok Kolaydı) */
.rating-row { display: flex; gap: var(--space-3); max-width: 560px; margin: var(--space-6) auto 0; }
.r-btn {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: .875rem var(--space-3); border-radius: var(--radius-lg); border: 1.5px solid var(--color-border);
  background: var(--color-surface-card); cursor: pointer; font-family: inherit; transition: transform .2s, box-shadow .2s; box-shadow: var(--shadow);
}
.r-btn:hover { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(15,23,42,.1); }
.r-btn-name { font-size: .875rem; font-weight: var(--fw-bold); margin-bottom: var(--space-1); }
.r-btn-interval { font-size: .68rem; color: var(--color-text-muted); }
.r-btn-hard:hover { border-color: #F87171; background: var(--color-danger-soft); }
.r-btn-hard .r-btn-name { color: var(--color-danger); }
.r-btn-good { border-color: rgba(79,70,229,.35); background: var(--color-primary-soft); }
.r-btn-good .r-btn-name { color: var(--color-primary); }
.r-btn-easy:hover { border-color: var(--color-accent-green-light); background: var(--color-success-soft); }
.r-btn-easy .r-btn-name { color: var(--color-success); }

/* Gradient hero/training card */
.gradient-card {
  background: linear-gradient(130deg, #3730A3 0%, var(--color-primary) 45%, var(--color-primary-l) 80%, var(--color-primary-l) 100%);
  border-radius: var(--radius-lg); padding: 1.625rem var(--space-8); color: var(--white);
  box-shadow: 0 12px 40px rgba(79,70,229,.28);
}

/* Responsive */
@media (max-width: 640px) {
  main { padding: var(--space-5) var(--space-4); }
  .site-nav { padding: 0 var(--space-4); gap: var(--space-4); }
  h1 { font-size: 1.6rem; }
  table { font-size: .82rem; }
  th, td { padding: var(--space-2) .6rem; }
  form { max-width: 100%; }
  .card-grid { grid-template-columns: 1fr; }
  .rating-row { gap: var(--space-2); }
  /* Mobile safety (#12): prevent media/table overflow on narrow screens. */
  img, video, iframe { max-width: 100%; height: auto; }
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  pre { overflow-x: auto; }
}
@media (max-width: 400px) {
  .site-nav { flex-wrap: wrap; height: auto; padding: var(--space-2) var(--space-4); }
}

/* Payment badges (footer band + checkout page) */
.payment-badges { display: flex; justify-content: center; padding: var(--space-3) 0; }
/* The KVKK notice sits above the payment badges in the same footer block. */
.footer-legal { text-align: center; margin: 0; padding-top: var(--space-3); font-size: .82rem; }
.footer-legal a { color: var(--color-text-muted); }
/* WhatsApp/email contact line, same footer band as .footer-legal above,
   its own rule since it needs a gap between the two links .footer-legal's
   single-link case never had to handle. */
.footer-contact { text-align: center; margin: 0; padding-top: var(--space-2); font-size: .82rem; display: flex; justify-content: center; align-items: center; gap: .5rem; flex-wrap: wrap; }
/* Pills, not plain links -- .footer-contact a's old flat text-link treatment
   read as inert during manual dev testing. Both channels get a solid fill,
   same split as contact_fab's .wa/.mail: WhatsApp green, mail
   --color-primary -- equal visual weight, consistent with the one other
   place this repo renders these two icons. Rendered via the shared
   .btn/.btn-sm/.btn-whatsapp/.btn-mail vocabulary (see those rules above)
   rather than a bespoke pill here, so hover/focus/text-decoration are
   inherited instead of re-derived. */
.checkout-payment-badge { display: block; max-width: 140px; height: auto; margin: 0 auto var(--space-4); }
