/* ---------------------------------------------------------------------------
   kamualimlari.com — targeted overrides on top of Tailwind.
   Kept small on purpose: anything expressible as a utility class stays in the
   markup. This file holds only what utilities cannot express.
   --------------------------------------------------------------------------- */

:root {
  --navy: #0f172a;
  --line: #e2e8f0;
  --canvas: #f8fafc;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  text-rendering: optimizeLegibility;
}

/* Dates, scores and quotas must line up in columns. */
.tabular-nums,
table,
.font-mono {
  font-variant-numeric: tabular-nums;
}

/* Consistent keyboard focus across native controls. */
:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid #0f172a;
  outline-offset: 2px;
  border-radius: 3px;
}

.bg-navy-900 :where(a, button):focus-visible {
  outline-color: #fbbf24;
}

/* Slim, neutral scrollbars — the default Windows bars are visually loud. */
* {
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 transparent;
}

*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

*::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border: 3px solid transparent;
  border-radius: 8px;
  background-clip: content-box;
}

*::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
  background-clip: content-box;
}

/* Deadline pill indicator for listings closing within three days. */
@keyframes kamu-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.82); }
}

.deadline-dot--urgent {
  animation: kamu-pulse 1.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

/* ------------------------------------------------------------------ ticker
   Each announcement fades up as it becomes the visible one. The class is added
   by app.js per slide rather than living on the container, so re-showing the
   same slide replays the animation. */
@keyframes kamu-ticker-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.ticker-item--enter {
  animation: kamu-ticker-in 240ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* The strip is one line tall on every viewport; a long announcement truncates
   rather than pushing the header down. The noscript rule in the partial relies
   on this staying a block-level item. */
[data-ticker-viewport] {
  min-height: 1.25rem;
}

/* Disclosure widgets (legal table of contents): the native triangle sits badly
   next to a Lucide chevron, and Chrome needs its own selector. */
summary {
  list-style: none;
}

summary::-webkit-details-marker {
  display: none;
}

/* ---------------------------------------------------------------- nav groups
   Header dropdowns are <details>, so the open/close behaviour is the browser's.
   This is only the presentation the element does not bring: a panel positioned
   out of flow, a chevron that turns, and a right-aligned panel for the last
   group so a wide panel cannot run past the container edge. */
.nav-group__chevron {
  transition: transform 160ms ease;
}

.nav-group[open] .nav-group__chevron {
  transform: rotate(180deg);
  color: #fbbf24;
}

@keyframes kamu-nav-panel-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.nav-group__panel {
  animation: kamu-nav-panel-in 130ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.nav-group:last-of-type .nav-group__panel {
  right: 0;
  left: auto;
}

/* Results region while a filter request is in flight: dim, but never collapse
   the layout — a jumping page height feels broken. */
[data-results][aria-busy='true'] {
  opacity: 0.45;
  transition: opacity 120ms linear;
  pointer-events: none;
}

[data-results] {
  transition: opacity 120ms linear;
}

/* Native date inputs render a low-contrast icon on Windows Chrome. */
input[type='date']::-webkit-calendar-picker-indicator {
  opacity: 0.55;
  cursor: pointer;
}

input[type='date']::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}

/* ------------------------------------------------------- kayıt ve takip
   Same reasoning as the quiz block below: app.js flips aria-pressed on markup
   the server rendered in the neutral state, so the "on" palette belongs here
   and exists once. */
[data-bookmark][aria-pressed='true'] {
  border-color: #fecaca;
  background: #fef2f2;
  color: #dc2626;
}

/* Lucide draws an outline heart; filling it is what reads as "saved". */
[data-bookmark][aria-pressed='true'] svg {
  fill: currentColor;
}

[data-tracker-option][aria-pressed='true'] {
  border-color: currentColor;
}

[data-tracker-option='basvurdum'][aria-pressed='true'] {
  background: #f0f9ff;
  color: #075985;
}

[data-tracker-option='bekliyor'][aria-pressed='true'] {
  background: #fffbeb;
  color: #92400e;
}

[data-tracker-option='mulakat'][aria-pressed='true'] {
  background: #ecfdf5;
  color: #065f46;
}

/* ------------------------------------------------------------------- quiz
   Answer feedback. The colours live here rather than in the markup because
   app.js toggles them on elements it did not render, and a utility list
   duplicated across JS and PHP drifts the moment either side is edited. */
[data-option][data-state='correct'] {
  border-color: #a7f3d0;
  background: #ecfdf5;
  color: #065f46;
}

[data-option][data-state='wrong'] {
  border-color: #fecaca;
  background: #fef2f2;
  color: #991b1b;
}

[data-option][data-state='missed'] {
  border-color: #a7f3d0;
  background: #f0fdf4;
}

[data-option][data-state='correct'] [data-option-letter],
[data-option][data-state='missed'] [data-option-letter] {
  border-color: #34d399;
  background: #34d399;
  color: #fff;
}

[data-option][data-state='wrong'] [data-option-letter] {
  border-color: #f87171;
  background: #f87171;
  color: #fff;
}

[data-question][data-answered] [data-option] {
  cursor: default;
}

/* The chosen option gets one short nudge — enough to register as feedback
   without turning a study page into an animation. */
@keyframes kamu-answer-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.014); }
  100% { transform: scale(1); }
}

@keyframes kamu-answer-shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3px); }
  75%      { transform: translateX(3px); }
}

[data-option][data-state='correct'] { animation: kamu-answer-pop 260ms ease-out; }
[data-option][data-state='wrong']   { animation: kamu-answer-shake 220ms ease-in-out; }

/* ------------------------------------------------------------- flip cards
   Two faces on one stacking context, so the deck cannot be read by anyone
   who has not turned the card over. */
.flip-card {
  perspective: 1200px;
}

.flip-card__inner {
  position: relative;
  display: block;
  width: 100%;
  min-height: 13.5rem;
  text-align: left;
  transform-style: preserve-3d;
  transition: transform 460ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.flip-card.is-flipped .flip-card__inner {
  transform: rotateY(180deg);
}

.flip-card__face {
  position: absolute;
  inset: 0;
  display: flex;
  overflow: auto;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.flip-card__face--back {
  transform: rotateY(180deg);
}

/* Scripting disabled: stack the faces instead of hiding half the deck. */
@media (scripting: none) {
  .flip-card__inner {
    min-height: 0;
    transform: none !important;
  }

  .flip-card__face {
    position: static;
    transform: none;
    overflow: visible;
  }

  .flip-card__face--back {
    border-top: 1px solid var(--line);
  }
}

/* Announcement body: the renderer emits its own utility classes, this only
   tightens the vertical rhythm between adjacent blocks. */
.announcement > *:first-child { margin-top: 0; }
.announcement > *:last-child  { margin-bottom: 0; }
.announcement h3 + ul,
.announcement h3 + p          { margin-top: 0.5rem; }

/* Anchor offset so headings do not hide under the sticky header. */
[id] {
  scroll-margin-top: 5.5rem;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ------------------------------------------------------------------- paint
   A results page carries a dozen cards and a question bank page carries more,
   and the visitor sees two of them. content-visibility lets the browser skip
   layout, style and paint for the rest until they are scrolled towards.

   `auto` in contain-intrinsic-size is the important half: the real height is
   remembered once a card has been rendered, so the scrollbar does not jump
   while the estimate is being corrected. Wrapped in @supports because the
   fallback — rendering everything, as before — is perfectly fine. */
@supports (content-visibility: auto) {
  [data-job],
  [data-question] {
    content-visibility: auto;
    contain-intrinsic-size: auto 240px;
  }

  /* Print needs every card laid out, whether it was scrolled to or not. */
  @media print {
    [data-job],
    [data-question] {
      content-visibility: visible;
    }
  }
}

/* ------------------------------------------------------------- deneme sınavı
   /kpss-sinav renders one complete paper and app.js pages through it. Every
   rule below is scoped to a [data-exam-state] that only JavaScript ever sets,
   so with scripting off the same markup stays a plain, fully revealed test. */

/* An option the candidate has marked but that has not been graded yet. Neutral
   on purpose: a colour here would leak the answer mid-exam. */
[data-option][data-state='picked'] {
  border-color: #0f172a;
  background: #f1f5f9;
  color: #0f172a;
}

[data-option][data-state='picked'] [data-option-letter] {
  border-color: #0f172a;
  background: #0f172a;
  color: #fff;
}

/* The last minute. Set by app.js on the clock itself. */
[data-exam-clock][data-exam-urgent] {
  color: #f87171;
}

/* intro — the rules are the page; the paper waits. */
[data-exam][data-exam-state='intro'] [data-exam-paper] {
  display: none;
}

/* running — one question visible, every answer sealed. app.js moves a single
   attribute; the paging itself is this rule. */
[data-exam][data-exam-state='running'] [data-exam-item]:not([data-exam-current]) {
  display: none;
}

[data-exam][data-exam-state='running'] [data-question-reveal] {
  display: none;
}

/* Paging scrolls the paper's top edge into view, which is the current question's
   top edge — this is what stops it landing under the sticky clock. */
[data-exam][data-exam-state='running'] [data-exam-paper] {
  scroll-margin-top: 9.5rem;
}

/* done — the whole paper is back, graded, with its solutions open again. */

/* Soru haritası. `data-state` carries whether a slot is answered and
   `aria-current` whether it is the one on screen, because a slot is routinely
   both and one attribute cannot say so. */
.exam-slot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.3rem;
  border: 1px solid #e2e8f0;
  border-radius: 0.25rem;
  background: #fff;
  color: #475569;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.exam-slot:hover {
  border-color: #cbd5e1;
  color: #0f172a;
}

.exam-slot[data-state='answered'] {
  border-color: #0f172a;
  background: #0f172a;
  color: #fff;
}

.exam-slot[aria-current='true'] {
  border-color: #f59e0b;
  background: #fef3c7;
  color: #92400e;
  box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.3);
}

.exam-slot--legend {
  width: 1rem;
  min-width: 1rem;
  height: 1rem;
  padding: 0;
  pointer-events: none;
}

/* The fullscreen element is its own viewport: it gets the page's background
   (otherwise the browser paints black behind it) and its own scrollbar, and the
   runtime bar sticks to its top rather than to where the site header used to be. */
[data-exam]:fullscreen {
  overflow-y: auto;
  background: #f8fafc;
  padding: 0 1rem 4rem;
}

[data-exam]:fullscreen [data-exam-bar] {
  top: 0;
}

[data-exam]:-webkit-full-screen {
  overflow-y: auto;
  background: #f8fafc;
  padding: 0 1rem 4rem;
}

[data-exam]:-webkit-full-screen [data-exam-bar] {
  top: 0;
}

/* --------------------------------------------------------------------- print
   Candidates print announcement pages to keep with their application file. */
@media print {
  [data-site-header],
  [data-no-print],
  footer {
    display: none !important;
  }

  body {
    background: #fff;
    font-size: 11pt;
  }

  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: 9pt;
    color: #475569;
    word-break: break-all;
  }

  .print-break-avoid {
    break-inside: avoid;
  }

  [data-exam][data-exam-state] [data-exam-paper],
  [data-exam][data-exam-state] [data-exam-item],
  [data-exam][data-exam-state] [data-question-reveal] {
    display: block !important;
  }
}
