/* Shared surface chrome — the pieces of interface that exist on more than one
   surface and therefore must not be defined twice.

   Before this sheet, the compact language selector's rules lived only in
   control-screens.css. The console looked right; the employer shell used the
   same markup with none of the styles, so opening its language menu reflowed
   the whole header; and the public portal never got the compact control at
   all — it rendered three full language names, 273px that could not shrink,
   on the one surface that is phone-first.

   Load order: after tokens.css, before any surface sheet, so a surface can
   still override. Every colour, radius and size here is a token. */

/* --- top-bar menus: language + notifications (native <details>) --------- */
/* The selector pattern: a <details> whose <summary> is the toggle and whose
   panel floats over the page. No JavaScript is required to operate it;
   menus.js only adds close-on-outside-tap and Escape, which native <details>
   lacks and which phones need — outside-tap is THE dismissal gesture there. */
.notif, .langsel, .surfaceswitch { position: relative; }
.notif > summary, .langsel > summary, .surfaceswitch > summary { list-style: none; cursor: pointer; }
.notif > summary::-webkit-details-marker,
.langsel > summary::-webkit-details-marker,
.surfaceswitch > summary::-webkit-details-marker { display: none; }
.langsel-toggle {
  display: inline-flex; align-items: center; gap: .35rem; height: 2.4rem; padding: 0 .6rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
}
.langsel-toggle:hover { background: var(--surface-2); }
.langsel-code { font-size: var(--fs-caption); font-weight: 700; }
.menu-panel {
  position: absolute; inset-inline-end: 0; top: calc(100% + .4rem); z-index: 40;
  min-width: 15rem; max-width: 92vw; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--elev-3); padding: .5rem;
}
.langsel-panel { min-width: 9rem; }
.menu-head {
  margin: .2rem .4rem .5rem; font-size: var(--fs-caption); text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); font-weight: 700;
}
.menu-empty { margin: .4rem; color: var(--muted); font-size: var(--fs-sm); }
.menu-item {
  display: block; width: 100%; text-align: start; padding: .5rem .6rem;
  border: 0; border-radius: var(--radius-sm); background: none; color: var(--text);
  font: inherit; cursor: pointer;
}
.menu-item:hover { background: var(--surface-2); }
.menu-item.is-active { background: var(--brand-soft); color: var(--brand-strong); font-weight: 700; }
.menu-foot {
  display: block; margin-top: .4rem; padding: .5rem .6rem;
  border-top: 1px solid var(--border); text-decoration: none;
  color: var(--brand-strong); font-weight: 600; font-size: var(--fs-sm);
}

/* --- the switch between the four surfaces -------------------------------- */
/* Same chassis as the language selector, deliberately: they sit beside each
   other in every header, and two controls one pixel apart that are built
   differently is how a header starts to look assembled rather than designed.

   The word beside the icon names the surface the reader is ON. It is the
   part that makes the control legible before it is opened — "you are in the
   cabinet, and there are other rooms" — so it is hidden only where there is
   genuinely no width for it. */
.surfaceswitch-toggle {
  display: inline-flex; align-items: center; gap: .4rem; height: 2.4rem; padding: 0 .6rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
}
.surfaceswitch-toggle:hover { background: var(--surface-2); border-color: var(--border-strong); }
.surfaceswitch-toggle svg { flex: none; color: var(--muted); }
.surfaceswitch[open] > .surfaceswitch-toggle { border-color: var(--brand); color: var(--brand-ink); }
.surfaceswitch[open] > .surfaceswitch-toggle svg { color: var(--brand); }
.surfaceswitch-word {
  font-size: var(--fs-caption); font-weight: 700; white-space: nowrap;
  max-width: 12ch; overflow: hidden; text-overflow: ellipsis;
}
.surfaceswitch-panel { min-width: 14rem; }

/* On a small phone the header is carrying a brand, a language code, a theme
   control and this; the word is the one piece that can go without losing a
   door. The icon and the accessible name stay.

   559px, not a width chosen for this control: the five sheets share one
   closed breakpoint vocabulary, and a sixth width invented here is how that
   set stopped meaning anything the last time. */
@media (max-width: 559px) {
  .surfaceswitch-word { display: none; }
  .surfaceswitch-toggle { padding: 0 .5rem; }
}

/* --- tap target -------------------------------------------------------- */
/* For the interactive element that is textually small but operationally
   heavy: the 8-character reference link that is the only way into a record,
   the action chip that fires a real request. Keeps the visual size; grows the
   touchable box. The coarse-pointer floor in tokens.css covers buttons and
   selects; this covers the anchors it cannot see. */
.tap-target { display: inline-flex; align-items: center; min-height: 2.4rem; }
@media (pointer: coarse) {
  .tap-target { min-height: var(--tap-min, 44px); }
}

/* --- the auth screens' corner ------------------------------------------ */
/* Sign-in, second-factor and role-mismatch are standalone documents with no
   header — deliberately, so an unproven session sees no workspace chrome.
   The language switch is the one piece of chrome they must still carry: an
   operator whose session expired should not face an English challenge with
   no way out of it. */
.auth-lang {
  position: absolute; top: 1rem; inset-inline-end: 1rem;
  padding-top: env(safe-area-inset-top);
}

/* --- theme toggle ------------------------------------------------------- */
/* Three states, one icon at a time; theme.js writes data-theme-state from
   the stored choice. Without JavaScript the button does nothing, so the
   resting look below (the half-lit "system" circle) is simply what it is. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; flex: none; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); cursor: pointer;
}
.theme-toggle:hover { background: var(--surface-2); }
.theme-toggle svg { width: 1.15rem; height: 1.15rem; }

.theme-toggle .icon-sun, .theme-toggle .icon-moon, .theme-toggle .icon-auto { display: none; }
.theme-toggle .icon-auto { display: block; }
.theme-toggle[data-theme-state="system"] .icon-auto { display: block; }
.theme-toggle[data-theme-state="light"] .icon-sun { display: block; }
.theme-toggle[data-theme-state="light"] .icon-auto { display: none; }
.theme-toggle[data-theme-state="dark"] .icon-moon { display: block; }
.theme-toggle[data-theme-state="dark"] .icon-auto { display: none; }

/* --- bottom navigation --------------------------------------------------- */
/* The phone-first primary navigation for the outward-facing roles: four
   plain links, one thumb, no JavaScript. The surface opts in by putting
   `has-bottomnav` on <body> — the bar itself renders on every width and
   this sheet decides when it shows, so the desktop keeps its header nav
   and the phone gets the bar, from one set of markup.

   Every consumer of `has-bottomnav` must reserve room: the bar overlays
   the page bottom, so `main` gains matching padding below the breakpoint. */
.bottom-nav {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 35;
  display: none;
  background: var(--surface); border-top: 1px solid var(--border);
  padding: 0.25rem 0.25rem calc(0.3rem + env(safe-area-inset-bottom));
}
.bottom-nav a {
  flex: 1 1 0; min-width: 0; min-height: 44px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.1rem; padding: 0.25rem 0;
  text-decoration: none; color: var(--muted);
  font-size: var(--fs-caption); font-weight: 600;
  /* Five tabs at 375px give each ~75px; "Документы" measures ~70px at 13px
     semibold, so the label keeps the readable floor and wins its pixels
     back from padding and tracking instead. */
  letter-spacing: -0.02em;
}
.bottom-nav a span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bottom-nav svg { width: 1.35rem; height: 1.35rem; flex: none; }
.bottom-nav a[aria-current="page"] { color: var(--brand-strong); }
.bottom-nav a { position: relative; }
.bottom-nav .nav-dot {
  position: absolute; top: 0.25rem; inset-inline-end: calc(50% - 1.1rem);
  width: 0.55rem; height: 0.55rem; border-radius: 50%;
  background: var(--danger); border: 2px solid var(--surface);
}
@media (max-width: 719px) {
  body.has-bottomnav .bottom-nav { display: flex; }
  body.has-bottomnav main { padding-bottom: calc(4.75rem + env(safe-area-inset-bottom)); }
}

/* --- sticky action bar --------------------------------------------------- */
/* A page's one primary verb, kept reachable while the page scrolls. Sticky,
   not fixed: it parks at the viewport bottom only while its page section is
   on screen, and where the bottom bar is showing it sits just above it. */
.action-bar {
  position: sticky; bottom: 0; z-index: 30;
  display: flex; gap: .5rem; align-items: center;
  padding: .6rem 0 calc(.6rem + env(safe-area-inset-bottom));
  background: var(--bg); border-top: 1px solid var(--border);
}
.action-bar .btn, .action-bar .button { flex: 1; text-align: center; justify-content: center; }
@media (max-width: 719px) {
  /* Audit fix: park the action bar flush ON TOP of the bottom nav, no gap.
     The nav is ~3.85rem of content + its bottom safe-area inset; matching
     that exactly (rather than a guessed 4.45rem) removes the strip of page
     that showed between the two bars. */
  body.has-bottomnav .action-bar {
    bottom: calc(3.85rem + env(safe-area-inset-bottom));
    margin-bottom: 0;
  }
}
@media (min-width: 720px) {
  .action-bar { position: static; border-top: 0; background: transparent; padding: 0; }
  .action-bar .btn { flex: none; }
}

/* --- cards-on-phone ------------------------------------------------------ */
/* An opt-in transform for simple outward-facing tables: below 640px each row
   becomes a bordered card and each cell a label/value line, the label taken
   from the cell's own data-label. For tables that neither sort nor select —
   the operator console's list framework keeps its table (sorting lives in
   the header links, and staff density is a decision, not an accident). */
@media (max-width: 639px) {
  table.cards-on-phone, table.cards-on-phone tbody { display: block; width: 100%; }
  table.cards-on-phone thead { display: none; }
  table.cards-on-phone caption { display: block; text-align: start; }
  table.cards-on-phone tbody tr {
    display: block; margin-block: var(--s-3, .75rem);
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: var(--s-2, .5rem) var(--s-3, .75rem);
  }
  table.cards-on-phone tbody td {
    display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
    border: 0; padding: 0.3rem 0; text-align: end;
  }
  table.cards-on-phone tbody td::before {
    content: attr(data-label);
    color: var(--muted); font-size: var(--fs-caption); font-weight: 600;
    text-align: start; flex: none;
  }
  table.cards-on-phone tbody td:first-child { font-weight: 600; }
}

/* M3: the header's sign-in door for guests. Same footprint as the theme
   toggle beside it, brand-coloured so it reads as THE way in at a glance. */
.header-login {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; flex: none;
  border: 1px solid var(--brand); border-radius: var(--radius-sm);
  background: var(--brand); color: var(--brand-contrast);
}
.header-login:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
.header-login svg { width: 1.15rem; height: 1.15rem; }

/* ==========================================================================
   Presentation wave: the touch layer.

   The product had 62 `:hover` rules across five stylesheets and not one
   `:active`. Hover does not exist on the device most candidates hold, so
   every designed reaction in the product was invisible to them: a tap either
   navigated or appeared to do nothing at all. One rule, scoped to coarse
   pointers so an eight-hour mouse user is unaffected, gives every control in
   the product the same 1px acknowledgement.

   `-webkit-tap-highlight-color` is cleared only on the elements that now
   answer for themselves; leaving it on a plain link keeps the browser's own
   feedback where nothing else provides any.
   ========================================================================== */
@media (pointer: coarse) {
  :is(button, .button, .btn, .wf-btn, .mode-action, .bottom-nav a, .menu-item, .chip-link):active {
    transform: translateY(1px);
    filter: brightness(0.94);
    -webkit-tap-highlight-color: transparent;
  }
}
@media (prefers-reduced-motion: no-preference) {
  :is(button, .button, .btn, .wf-btn, .mode-action):active {
    transition: transform var(--dur-1, 140ms) var(--ease-out, ease-out);
  }
}

/* The keyboard's own space. The bottom bar is fixed and the contact button
   floats above it, so on a 360x640 phone the two together cover roughly a
   quarter of what is left once the soft keyboard opens — directly over the
   field being typed into. `:has()` is the whole fix on a modern WebView;
   portal.js adds a body class for older ones. */
body:has(input:focus, textarea:focus, select:focus) :is(.bottom-nav, .contact-fab),
body.is-typing :is(.bottom-nav, .contact-fab) { display: none; }

/* Cross-document view transitions. Between page loads the header, the bottom
   bar and the floating button are re-rendered from scratch and the whole
   screen blinks; naming them lets the browser keep them still and crossfade
   only what changed. Older WebViews ignore every line of this. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  .site-header { view-transition-name: site-header; }
  .bottom-nav { view-transition-name: bottom-nav; }
  .contact-fab { view-transition-name: contact-fab; }
}

/* The in-flight state. It is set by portal.js only while a real request is
   actually running, never on a timer: a pending state the system is not
   backing is the same lie as a fake spinner. */
[data-pending] { position: relative; cursor: progress; }
[data-pending]::after {
  content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 2px;
  border-radius: 2px; background: var(--brand);
  transform-origin: left center;
}
@media (prefers-reduced-motion: no-preference) {
  [data-pending]::after { animation: zxPending 1.1s var(--ease-in-out, ease-in-out) infinite; }
  @keyframes zxPending {
    0%   { transform: scaleX(0);   opacity: 0.9; }
    50%  { transform: scaleX(1);   opacity: 1; }
    100% { transform: scaleX(0);   opacity: 0.9; transform-origin: right center; }
  }
}
@media (prefers-reduced-motion: reduce) {
  [data-pending]::after { transform: scaleX(1); opacity: 0.5; }
}

/* --- the shared brand mark -------------------------------------------------
   Layout only. The identity — gradient, radius, letterforms — lives inside
   partials/brand.html so that /for-employers/, which links no shared
   stylesheet on purpose, still renders the same mark as everything else. */
.zx-brand { display: inline-flex; align-items: center; gap: 10px; flex: none; text-decoration: none; color: var(--text); }
.zx-brand-mark { width: 36px; height: 36px; flex: none; line-height: 0; }
.zx-brand-mark svg { display: block; width: 100%; height: 100%; }
.zx-brand-name { font-weight: 800; font-size: 17px; letter-spacing: -0.01em; white-space: nowrap; }
@media (max-width: 719px) {
  .zx-brand { gap: 8px; }
  .zx-brand-mark { width: 30px; height: 30px; }
  .zx-brand-name { font-size: 15px; }
}

/* --- two languages in reach, the rest in the menu --------------------------
   The quick buttons and the menu toggle are one control visually: a single
   bordered group, so the header reads as one language area rather than two
   competing ones. Sized for the 44px floor at every width, because this is
   the control the catalogue's Bulgarian readers use first. */
.langquick { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
.langquick-btn {
  height: 2.25rem; min-width: 2.25rem; padding: 0 0.5rem; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--muted); font: inherit; font-size: var(--fs-caption);
  font-weight: 700; letter-spacing: .02em; cursor: pointer;
}
.langquick-btn:hover { background: var(--surface-2); color: var(--text); }
.langquick-btn[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand-strong); }
.langquick .langsel-toggle { height: 2.25rem; min-width: 2.25rem; }
@media (max-width: 719px) {
  /* Every language control clears the tap floor here — this row is the one
     an employer uses on a phone. */
  .langquick-btn, .langquick .langsel-toggle { height: 2.75rem; min-width: 2.75rem; }
}
