/* Global search dialog and shortcut tiles, keyboard shortcut hints, API documentation page.
   Split out of theme.css (original lines 6092-6556) — 2026-08-18,
   CSS @layer restructuring step 2 (Basecamp "Fra Fizzy-gjennomgang:
   CSS-arkitektur"). Numeric filename prefix controls load order (see
   app/helpers/application_helper.rb#theme_stylesheet_link_tag) —
   files are concatenated in this exact original order, so no cascade
   tie-break changes. */
@layer overrides {
/* Global search dialog (workspaces/_page_header.html.erb, search_controller.js,
   keyboard_shortcut_controller.js — Shift+J or the header search icon).
   Positioned like .app-confirm-dialog, but tall/anchored higher since it
   holds a growing results list rather than a couple of sentences. */
.global-search__dialog {
    position: fixed;
    top: 15%;
    left: 50%;
    /* Torleiv, 2026-08-15 ("Midtstill shift+j-meny over hovedseksjon"):
       left: 50% centers on the FULL viewport — same bug as
       .header-brand/.header-breadcrumb had (see their own comments), just
       here via a native <dialog>'s own fixed positioning instead of flex
       centering. The real content column shifts left by half the open
       sidebar's width, so this needs the same correction to land back
       over it instead of over the (now partly sidebar-covered) middle of
       the whole screen. */
    transform: translateX(calc(-50% - var(--sidebar-width, 0px) / 2));
    margin: 0;
    width: 32rem;
    max-width: calc(100dvw - var(--space-6));
    max-height: 70vh;
    /* No title sits above the input here (unlike .document-nav-gear__dialog),
       so the top inset alone has to clear .dialog-close's own footprint
       (space-3 offset + its 2rem height) or the X sits on top of the input. */
    padding: calc(var(--space-3) + 2rem) var(--space-4) var(--space-4);
    border: var(--card-border);
    border-radius: var(--card-radius);
    background: var(--card-bg);
    box-shadow: var(--dialog-shadow);
    overflow: hidden;
}

/* [open] guard is load-bearing: a bare `display:` on the dialog itself
   would override the UA stylesheet's `dialog:not([open]) { display:none }`,
   making it visible at rest instead of only after showModal(). */
.global-search__dialog[open] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.global-search__dialog::backdrop {
    background: var(--dialog-backdrop);
}

.global-search__input {
    width: 100%;
    padding: var(--space-3);
    border: var(--card-border);
    border-radius: var(--radius-md);
    font-size: var(--text-size-lg);
}

.global-search__input:focus {
    outline: none;
    border-color: var(--signal-color);
}

.global-search__results {
    display: block;
    overflow-y: auto;
}

.global-search__empty {
    padding: var(--space-4) var(--space-2);
    color: color-mix(in srgb, var(--text-900) 50%, transparent);
    font-size: var(--text-size-base);
    text-align: center;
}

/* Torleiv, 2026-08-20 (#10224407226): the query-syntax cheat sheet shown
   under the empty-state message — quiet/small like .global-search__empty
   itself (a reference, not something worth drawing the eye to), listed
   rather than run together since six short rules read faster as a list
   than as a paragraph. */
.global-search__syntax-hint {
    list-style: none;
    margin: 0 auto;
    padding: 0 var(--space-4) var(--space-4);
    max-width: 320px;
    color: color-mix(in srgb, var(--text-900) 50%, transparent);
    font-size: var(--text-size-sm);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.global-search__syntax-hint code {
    font-size: 0.9em;
}

.global-search__result-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

/* Static quick links (Mine dokumenter/Bokmerker/Personer/Mine oppgaver),
   shown above the dynamic results as four equal square tiles in a row
   (Torleiv, 2026-08-10, with a screenshot — replaces an earlier stacked-
   sections layout, see the view comment) — separated with a rule so the
   tiles and the search results don't blur together. */
.global-search__shortcuts {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-2);
    padding-bottom: var(--space-2);
    border-bottom: var(--card-border);
}

/* Square via aspect-ratio rather than a fixed height, so the row still
   reflows sanely if the dialog's own width ever changes (e.g. a narrower
   viewport) — same card language as .workspace-shortcut (radius, bg,
   hover lift), just centered icon-over-label instead of a title+text
   block, and small enough that four fit one row at this dialog width. */
.global-search__shortcut-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    aspect-ratio: 1;
    padding: var(--space-2);
    border-radius: var(--card-radius);
    background: var(--card-bg);
    color: inherit;
    text-decoration: none;
    text-align: center;
    transition: transform 0.15s ease;
    position: relative;
}

.global-search__shortcut-tile:hover {
    transform: translateY(-1px);
}

.global-search__shortcut-tile-label {
    font-size: var(--text-size-xs);
    line-height: 1.2;
}

/* Positioning context for the hint badge below — lets it center directly
   above THIS icon specifically regardless of the tile's own padding/label
   height, rather than the tile's corner (Torleiv, 2026-08-11, screenshot:
   the old corner position read as an unrelated stray mark next to tile 1,
   not obviously "this icon's shortcut"). */
.global-search__shortcut-tile-icon {
    position: relative;
    display: inline-flex;
}

/* Shift+digit hint (Shift+1/2/3/4 — see keyboard_shortcut_controller.js's
   openShortcutTile/showShortcutHints), centered directly above its own
   icon. Two separate <kbd> keycaps rather than a single bare digit —
   Torleiv, 2026-08-11: needed to read unambiguously as ONE key combo
   (Shift held, then the digit), not just "press 2". Only ever visible
   while Shift is actually held (body.shift-shortcuts-active) — permanent
   keycaps on every tile would just be visual noise for the far more
   common case of clicking instead of using the keyboard.
   No transition here on purpose — tested one (opacity/transform easing)
   and found it gets stuck mid-animation specifically when the ancestor
   class change happens while this dialog is open via showModal(): the
   badge fades IN correctly but never fades back OUT, staying visible
   after Shift is released, since <dialog>'s top-layer promotion doesn't
   reliably settle a transition retriggered by an ancestor selector match
   changing. A plain instant toggle has no such failure mode. */
.global-search__shortcut-tile-hint {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 2px;
    display: flex;
    gap: 2px;
    opacity: 0;
    pointer-events: none;
}

body.shift-shortcuts-active .global-search__shortcut-tile-hint {
    opacity: 1;
}

.global-search__shortcut-tile-hint kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 0.25rem;
    border-radius: var(--radius-sm);
    /* #10278596584 (dark mode): this keycap's own background is a fixed
       #fff, not var(--card-bg) — deliberately always white, like a real
       physical key, regardless of page theme (see this rule's own
       "reuses the exact same kbd keycap look" comment above). border/
       color used var(--text-900) though, which flips to a LIGHT color in
       dark mode — composited against the still-white background, that
       read as pale-on-white, nearly invisible. Pinned to the literal
       Blekk ink instead, since the surface they sit on never changes. */
    background: #fff;
    border: 1px solid color-mix(in srgb, #1A1C1B 20%, transparent);
    box-shadow: 0 1px 0 rgba(28, 25, 20, 0.15);
    color: color-mix(in srgb, #1A1C1B 75%, transparent);
    font-size: 9px;
    font-weight: 700;
    font-family: inherit;
    line-height: 1;
}

/* Shift+key hint badges next to header shortcut triggers (Home, search,
   avatar/user menu, Sidefelt) — Torleiv, 2026-08-16, referencing
   Basecamp's own persistent per-shortcut badges, first built as
   always-visible; then, same day, reversed: "Snarveiene må bare vises
   når en holder inn shift-knappen" — so these now use the SAME
   hold-Shift-to-reveal mechanism as the digit-tile hints above
   (body.shift-shortcuts-active), not a permanently-visible badge.
   Reuses the exact same kbd keycap look as
   .global-search__shortcut-tile-hint for one consistent "what a
   keyboard shortcut badge looks like". */
.header-shortcut-hint {
    display: inline-flex;
    gap: 2px;
    margin-left: var(--space-1);
    opacity: 0;
    pointer-events: none;
}

body.shift-shortcuts-active .header-shortcut-hint {
    opacity: 1;
}

/* Torleiv, Basecamp #10217877358 ("Snarveiene skal vises ... også i
   menyen"): the avatar menu's own items are a full-width flex row
   (icon + label), so the hint needs to be pushed to the row's own right
   edge instead of just trailing the label text with a small gap — same
   right-aligned-badge convention as sand_ui's own key-value rows,
   rather than the compact "sits right after the label" look the header
   nav's own bare Hjem/Søk triggers use (those rows are already sized to
   their content, nothing to push against). */
.header-user-menu__item .header-shortcut-hint {
    margin-left: auto;
}

.header-shortcut-hint kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 0.25rem;
    border-radius: var(--radius-sm);
    /* #10278596584 (dark mode): this keycap's own background is a fixed
       #fff, not var(--card-bg) — deliberately always white, like a real
       physical key, regardless of page theme (see this rule's own
       "reuses the exact same kbd keycap look" comment above). border/
       color used var(--text-900) though, which flips to a LIGHT color in
       dark mode — composited against the still-white background, that
       read as pale-on-white, nearly invisible. Pinned to the literal
       Blekk ink instead, since the surface they sit on never changes. */
    background: #fff;
    border: 1px solid color-mix(in srgb, #1A1C1B 20%, transparent);
    box-shadow: 0 1px 0 rgba(28, 25, 20, 0.15);
    color: color-mix(in srgb, #1A1C1B 75%, transparent);
    font-size: 9px;
    font-weight: 700;
    font-family: inherit;
    line-height: 1;
}

/* Icon-only triggers (search, avatar) have no visible label to sit the
   badge inline after — a small corner overlay instead, same idea as
   .global-search__shortcut-tile-icon's own badge placement. Needs
   position: relative on the trigger/wrapper itself (added inline where
   used) so this positions against that element, not the header at large. */
.header-shortcut-hint--corner {
    position: absolute;
    bottom: -4px;
    right: -4px;
    margin-left: 0;
}

.global-search,
.header-user-menu__trigger {
    position: relative;
}

.global-search__result {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-md);
    color: inherit;
    text-decoration: none;
}

.global-search__result:hover,
.global-search__result--active {
    background: color-mix(in srgb, var(--text-900) 6%, transparent);
}

/* Wraps title-row + the optional context line (module/excerpt) so they
   stack, while title-row itself stays a row (title/subtitle side by
   side) — min-width: 0 is load-bearing, without it a flex child won't
   shrink below its content's natural width, so the title/context
   ellipsis truncation below never actually kicks in. */
.global-search__result-text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.global-search__result-title-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.global-search__result-title {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.global-search__result-subtitle {
    flex-shrink: 0;
    /* 15.09.2026: 45 % ink over the card measured about 2.9:1; small text
       needs 4.5:1. --text-700 is the muted step that still passes, in
       both themes. Same below and in the tasks panel. */
    color: var(--text-700);
    font-size: var(--text-size-xs);
}

/* Where a Document/Folder lives, plus a content-match excerpt when that's
   why it matched (see SearchController#node_location/#excerpt_around) —
   without this a content-only hit gave no visible reason it was in the
   list at all. */
.global-search__result-context {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-700);
    font-size: var(--text-size-xs);
}

/* API documentation page (app/views/api_docs/show.html.erb) */
.api-docs__code {
    overflow-x: auto;
    padding: var(--space-3);
    border-radius: var(--card-radius);
    background: var(--card-bg-muted);
    border: var(--card-border);
    font-family: ui-monospace, monospace;
    font-size: var(--text-size-sm);
    white-space: pre-wrap;
    word-break: break-all;
}

.api-docs__table-wrap {
    overflow-x: auto;
    padding: 0;
}

.api-docs__table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-size-base);
}

.api-docs__table th,
.api-docs__table td {
    padding: var(--space-2) var(--space-3);
    text-align: left;
    border-bottom: 1px solid color-mix(in srgb, var(--text-900) 8%, transparent);
    vertical-align: top;
}

.api-docs__table th {
    color: var(--text-500, #666);
    font-size: var(--text-size-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.api-docs__table tr:last-child td {
    border-bottom: none;
}

.api-docs__table code {
    font-family: ui-monospace, monospace;
    font-size: var(--text-size-sm);
}

/* The shared .page-title-header__back sits bottom-left, absolutely
   positioned within the header's own generous padding — fine on every
   other page that uses it, but on api_docs its left edge lines up with
   the TOC sidebar starting right below, reading as if it belongs to the
   sidebar rather than the page (Torleiv, 2026-08-12). Flow it above the
   title instead, just on this page — a plain, page-scoped override, not
   a change to the shared rule every other back-link page relies on. */
.api-docs-page .page-title-header__back {
    position: static;
    text-align: left;
    margin-bottom: var(--space-4);
}

/* API docs page layout — a small, self-contained TOC + prose column.
   Deliberately its own sticky (position:sticky, no JS, no shared
   --page-header-height var) rather than reusing .document-layout/
   .document-focus, which drive the still-unresolved sticky-header bug —
   this page has no reason to share that machinery or its risk. */
.api-docs-layout {
    display: flex;
    align-items: flex-start;
    gap: var(--space-6);
}

.api-docs-toc {
    position: sticky;
    /* Same real-measured-height variable .document-page-header uses (set
       by sticky_offset_controller.js) — a guessed small offset here let
       the sidebar's own sticky position slide up underneath the app's
       actual, taller sticky top bar once scrolled (Torleiv, 2026-08-12). */
    top: calc(var(--page-header-height, 60px) + var(--space-4));
    flex: none;
    width: 220px;
}

.api-docs-toc__label {
    margin: 0 0 var(--space-2);
    color: var(--text-500, #888);
    font-size: var(--text-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.api-docs-toc__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin: 0 0 var(--space-4);
    padding: 0;
    list-style: none;
}

.api-docs-toc__list a {
    display: block;
    padding: var(--space-1) 0;
    color: var(--text-500, #888);
    font-size: var(--text-size-sm);
    line-height: 1.4;
    text-decoration: none;
}

.api-docs-toc__list a:hover {
    color: var(--text-900, #111);
}

.api-docs-toc__copy {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--card-radius);
    background: var(--card-bg-muted);
    border: var(--card-border);
    color: var(--text-700, #444);
    font-size: var(--text-size-sm);
    cursor: pointer;
}

.api-docs-toc__copy:hover {
    color: var(--text-900, #111);
}

.api-docs-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.api-docs-content p {
    margin: 0 0 var(--space-3);
    line-height: 1.6;
    max-width: 68ch;
}

.api-docs-content p:last-child {
    margin-bottom: 0;
}

/* Mobile (#10276047895, found live): .api-docs-layout's own
   align-items: flex-start (needed for the desktop row layout, so the
   sidebar and content column don't stretch to match each other's
   height) has a second effect once flex-direction switches to column
   below — flex-start on the cross axis sizes each child to its own
   shrink-to-fit content width instead of stretching to fill the
   column, so .api-docs-content grew to whatever width its widest
   child (a .api-docs__code block, or a p's own max-width: 68ch)
   preferred, well past a phone's viewport, dragging the whole
   document wider than the screen with it (not just that one element
   overflowing its own box — the entire page needed horizontal
   scroll/pinch-zoom). align-items: stretch here forces the column
   back to the container's own full width. */
@media (max-width: 900px) {
    .api-docs-layout {
        flex-direction: column;
        align-items: stretch;
    }

    .api-docs-toc {
        position: static;
        width: auto;
    }
}

/* #10281061392 (mobile round 2): four square tiles in a row need ~90px
   each once the label ("Mine dokumenter") sets the column's minimum —
   4 × 89px + gaps is 380px inside a dialog whose content box is 317px
   at 375px, so the last tile ran 45px past the dialog's edge (measured).
   Two columns of compact icon-and-label rows instead: everything stays
   reachable, and the dialog keeps its height for the results below
   rather than spending it on four 150px squares. Desktop is untouched. */
@media (max-width: 640px) {
    .global-search__shortcuts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .global-search__shortcut-tile {
        aspect-ratio: auto;
        flex-direction: row;
        justify-content: flex-start;
        gap: var(--space-2);
        padding: var(--space-2) var(--space-3);
        text-align: left;
    }
}


} /* @layer overrides */
