/*
 * Visual system for the JKN Management admin pages (Users, Email Settings,
 * Security/Turnstile). Everything here is scoped under .jkn-page (or is a
 * new, uniquely-named component class) so it never touches the look of the
 * rest of the app.
 */

/* ---------- gradient icon badges ---------- */

.icon-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: 11px;
    color: #fff;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1;
}

.icon-badge-xs {
    width: 24px;
    height: 24px;
    border-radius: 7px;
    font-size: .68rem;
}

.icon-badge-sm {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    font-size: .82rem;
}

.icon-badge-lg {
    width: 54px;
    height: 54px;
    border-radius: 15px;
    font-size: 1.4rem;
}

.icon-badge-blue {
    background: linear-gradient(135deg, #60a5fa 0%, #3b5bdb 100%);
    box-shadow: 0 6px 14px -5px rgba(59, 91, 219, .6);
}

.icon-badge-purple {
    background: linear-gradient(135deg, #c084fc 0%, #7c3aed 100%);
    box-shadow: 0 6px 14px -5px rgba(124, 58, 237, .55);
}

.icon-badge-teal {
    background: linear-gradient(135deg, #5eead4 0%, #0891b2 100%);
    box-shadow: 0 6px 14px -5px rgba(8, 145, 178, .55);
}

.icon-badge-amber {
    background: linear-gradient(135deg, #fcd34d 0%, #f97316 100%);
    box-shadow: 0 6px 14px -5px rgba(249, 115, 22, .5);
}

.icon-badge-green {
    background: linear-gradient(135deg, #6ee7b7 0%, #059669 100%);
    box-shadow: 0 6px 14px -5px rgba(5, 150, 105, .5);
}

.icon-badge-red {
    background: linear-gradient(135deg, #fca5a5 0%, #dc2626 100%);
    box-shadow: 0 6px 14px -5px rgba(220, 38, 38, .5);
}

.icon-badge-slate {
    background: linear-gradient(135deg, #94a3b8 0%, #475569 100%);
    box-shadow: 0 6px 14px -5px rgba(71, 85, 105, .45);
}

/* ---------- page header banner ---------- */

.jkn-page-header {
    display: flex;
    align-items: center;
    /* Lets the optional .jkn-page-header-stats cluster (below) drop to its
       own line instead of forcing the title/subtitle to shrink when the
       window is narrower than title + stats can share. */
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}

.jkn-page-header .icon-badge {
    margin-right: 1rem;
}

.jkn-page-title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    color: #1e293b;
}

.jkn-page-subtitle {
    margin: .1rem 0 0;
    color: #64748b;
    font-size: .875rem;
}

/* Compact at-a-glance counts docked to the right of a page header (first
   use: admin/users/index.blade.php's Total/Admin JKN/Facility-Scoped
   counts) — the same jkn-stat-value/jkn-stat-label pairing a full
   .jkn-stat-tile uses, just without the card/icon-badge chrome, so three
   numbers can sit inline with the title instead of costing a whole extra
   .jkn-bento-stats row. No flex `gap` (IE11/Windows-7 safe, matching the
   .jkn-bento-stats fallback below) — spacing is margin-left on siblings. */
.jkn-page-header-stats {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-left: auto;
}

.jkn-header-stat {
    text-align: right;
    margin-left: 1.75rem;
}

.jkn-header-stat:first-child {
    margin-left: 0;
}

/* Primary action docked at the far right of a page header, after the
   optional stats cluster (first use: admin/users/index.blade.php's "Add
   User" — previously a card-header button, promoted up here so the card
   below can drop its own header entirely). Only .jkn-page-header-stats
   carries the auto margin that pushes the right-hand group over; this just
   needs a fixed gap from whatever it sits next to. */
.jkn-page-header-action {
    margin-left: 1.25rem;
}

.jkn-page-header-action:only-child {
    margin-left: auto;
}

/* ---------- tabs ---------- */

.jkn-page .nav-tabs {
    border-bottom: none;
    background: #f1f5f9;
    display: inline-flex;
    padding: .3rem;
    border-radius: 10px;
    margin-bottom: 1.25rem;
}

.jkn-page .nav-tabs .nav-item {
    margin-bottom: 0;
    margin-right: .25rem;
}

.jkn-page .nav-tabs .nav-link {
    border: none;
    border-radius: 8px;
    padding: .5rem 1rem;
    font-weight: 600;
    font-size: .875rem;
    color: #475569;
    transition: all .15s ease;
}

.jkn-page .nav-tabs .nav-link:hover {
    color: #1e293b;
    isolation: isolate;
}

.jkn-page .nav-tabs .nav-link.active {
    background: #fff;
    color: #3b5bdb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

/* ---------- cards ---------- */

.jkn-page .card {
    border: none;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 10px 24px -16px rgba(15, 23, 42, .25);
    margin-bottom: 1.25rem;
}

.jkn-page .card-header {
    background: #fff;
    border-bottom: 1px solid #eef1f5;
    border-radius: 14px 14px 0 0 !important;
    padding: .9rem 1.15rem;
    display: flex;
    align-items: center;
}

/* AdminLTE's .card-primary:not(.card-outline)>.card-header rule (3 class
   selectors) outweighs the plain white background above (2 class
   selectors) and paints a solid blue bar regardless of it — this repeats
   the same selector shape with an extra .jkn-page ancestor so it wins on
   specificity instead of relying on stylesheet order. */
.jkn-page .card-primary:not(.card-outline) > .card-header {
    background-color: #fff;
}

.jkn-page .card-header .card-title-text {
    font-weight: 700;
    color: #1e293b;
    font-size: .95rem;
}

/* AdminLTE's actual rule is ".card-primary:not(.card-outline)>.card-header,
   ...>.card-header a{color:#fff}" — it targets <a> tags directly, so its
   3-classes-plus-a-tag specificity narrowly beats a plain 3-class override;
   the extra .btn qualifier (already on the element) pushes this to 4
   classes so it wins outright rather than relying on a specificity tie.
   Without this, a .btn-outline-primary sitting in the same header (e.g.
   "Change Facility") inherits that white text over its own transparent
   background — invisible white-on-white. */
.jkn-page .card-header .btn.btn-outline-primary {
    color: #3b5bdb;
}

/* ...and that same specificity bump means this resting-state fix also now
   outranks .btn-outline-primary:hover{color:#fff} (Bootstrap) inside a
   header, which left hover text indigo-on-indigo-gradient. Restore white
   specifically on hover to match the fill this file already gives
   .btn-outline-primary:hover elsewhere. */
.jkn-page .card-header .btn.btn-outline-primary:hover {
    color: #fff;
}

.jkn-page .card-body {
    padding: 1.25rem;
}

.jkn-page .card.card-outline {
    border-top: none;
}

/* ---------- table ---------- */

.jkn-page .table thead th {
    border-top: none;
    border-bottom: 2px solid #eef1f5;
    text-transform: uppercase;
    font-size: .68rem;
    letter-spacing: .05em;
    color: #94a3b8;
    font-weight: 700;
    padding: .6rem .75rem;
}

.jkn-page .table td {
    vertical-align: middle;
    padding: .8rem .75rem;
    border-top: 1px solid #f1f5f9;
}

.jkn-page .table tbody tr {
    transition: background-color .1s ease;
}

.jkn-page .table tbody tr:hover {
    background-color: #f8fafc;
}

/* Role filter + search, one row (admin/users/index.blade.php — replaces the
   card-header that used to hold the "All Users" title and Add button, both
   promoted up into .jkn-page-header). No flex `gap` (IE11/Windows-7 safe,
   same reasoning as .jkn-page-header-stats) — the search box's margin-left:
   auto is the only spacing rule needed since it's the last item. */
.jkn-table-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.jkn-table-search {
    position: relative;
    margin-left: auto;
}

.jkn-table-search i {
    position: absolute;
    top: 50%;
    left: .7rem;
    transform: translateY(-50%);
    color: #94a3b8;
    font-size: .75rem;
    pointer-events: none;
}

.jkn-table-search input {
    width: 220px;
    padding-left: 2rem;
    border-radius: 999px;
}

.jkn-table-search input:focus {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .15);
}

/* DataTables' own generated info/pagination controls, reskinned to the
   page's own ink/blue tokens instead of the datatables.min.css default
   theme so they read as part of this design system, not a bundled plugin. */
.jkn-page .dataTables_wrapper .dataTables_info {
    color: #64748b;
    font-size: .82rem;
    padding-top: .85rem;
}

.jkn-page .dataTables_wrapper .dataTables_paginate .paginate_button {
    border-radius: 8px;
    padding: .35rem .7rem;
    margin-left: .2rem;
    color: #475569 !important;
    border: none !important;
    background: transparent !important;
}

.jkn-page .dataTables_wrapper .dataTables_paginate .paginate_button.disabled {
    color: #cbd5e1 !important;
}

.jkn-page .dataTables_wrapper .dataTables_paginate .paginate_button:hover {
    color: #1e293b !important;
    background: #f1f5f9 !important;
}

/* Flat fill, not a gradient — Gradient-Means-Icon reserves gradients for
   icon badges/primary buttons/stat-tile icons, and a pagination pill is
   none of those. */
.jkn-page .dataTables_wrapper .dataTables_paginate .paginate_button.current {
    color: #fff !important;
    background: #3b5bdb !important;
}

.jkn-page .dataTables_wrapper .dataTables_processing {
    color: #64748b;
    font-weight: 600;
}

/* ---------- buttons ---------- */

.jkn-page .btn {
    border-radius: 8px;
    font-weight: 600;
    font-size: .85rem;
}

/* Transparent border, not `border: none`. Bootstrap's .btn ships a 1px
   border, so removing it outright made every gradient button 2px shorter
   than a bordered neutral beside it — visible as mismatched heights
   wherever the two share a row or a modal footer. background-clip defaults
   to border-box, so the gradient still fills the border area and the paint
   is identical. */
.jkn-page .btn-primary {
    background: linear-gradient(135deg, #60a5fa 0%, #3b5bdb 100%);
    border: 1px solid transparent;
    box-shadow: 0 4px 12px -4px rgba(59, 91, 219, .55);
    transition: all .15s ease;
}

.jkn-page .btn-primary:hover,
.jkn-page .btn-primary:focus {
    filter: brightness(1.06);
    box-shadow: 0 6px 16px -4px rgba(59, 91, 219, .65);
    transform: translateY(-1px);
}

/* Transparent border for the same height-parity reason as .btn-primary. */
.jkn-page .btn-danger {
    background: linear-gradient(135deg, #fca5a5 0%, #dc2626 100%);
    border: 1px solid transparent;
    box-shadow: 0 4px 12px -4px rgba(220, 38, 38, .45);
}

.jkn-page .btn-danger:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
}

.jkn-page .btn-outline-primary {
    border-color: #c7d2fe;
    color: #3b5bdb;
}

.jkn-page .btn-outline-primary:hover {
    background: linear-gradient(135deg, #60a5fa 0%, #3b5bdb 100%);
    border-color: transparent;
}

/* ---------- buttons: neutral variants ----------
 * btn-secondary (Bootstrap) and btn-default (AdminLTE) were the only two
 * variants this system never claimed, so every Cancel/Close/Download on
 * these screens rendered as a raw framework slab beside gradient siblings.
 * Both stay flat by design — the Gradient-Means-Icon rule reserves
 * gradients for icon badges and the primary/danger pair, so a neutral that
 * gradients would read as a third primary.
 *
 * AdminLTE's .btn-default is (0,1,0) and its :hover (0,2,0); the .jkn-page
 * prefix clears both without needing !important.
 */

.jkn-page .btn-default,
.jkn-page .btn-secondary {
    background-color: #f8fafc;
    border-color: #e2e8f0;
    color: #475569;
    box-shadow: none;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.jkn-page .btn-default:hover,
.jkn-page .btn-secondary:hover {
    background-color: #f1f5f9;
    border-color: #cbd5e1;
    color: #1e293b;
}

/* ---------- buttons: icon + label pairing ----------
 * Direct-child selector, deliberately: every icon on this surface is a bare
 * <i class="fa ..."> immediately inside the button. Audited before shipping
 * — no other .jkn-page view puts an <i> inside a .btn (the legacy row
 * actions in settings/facility.blade.php and admin/users/index.blade.php
 * use <span class="fa ...">), so this cannot leak.
 *
 * The markup also keeps a literal space between icon and label. Not
 * redundancy: if this stylesheet ever fails to load, the space alone still
 * separates glyph from text.
 */

.jkn-page .btn > i {
    margin-right: .25rem;
}

/* ---------- buttons: icon-only (table row actions) ----------
 * Marked explicitly rather than detected. No selector can tell "<i> plus a
 * label" from "<i> alone" on the engines this app must run on: :has() is
 * Chrome 105+ (the Windows 7 counters stop at 109), and i:only-child
 * matches BOTH cases because :only-child counts element children, not text
 * nodes.
 *
 * Width only, never height. .btn-group is inline-flex with the default
 * align-items:stretch, so an explicit height would win over stretch and
 * desync these from a labelled btn-sm sibling (locations.blade.php pairs an
 * icon-only Edit with a labelled Settings in one group). Letting btn-sm's
 * own vertical padding set the height makes the match exact by
 * construction.
 */

.jkn-page .btn.jkn-btn-icon {
    width: 30px;
    padding-left: 0;
    padding-right: 0;
    text-align: center;
}

/* Cancels the pairing margin above so the glyph sits dead-centre in the
   30px box. fa-fw's own width:1.25em is left alone — that is what makes
   every glyph in a row occupy an identical advance regardless of shape. */
.jkn-page .btn.jkn-btn-icon > i {
    margin-right: 0;
}

/* ---------- buttons: row-action group ----------
 * Bootstrap's .btn-group > .btn:not(:last-child):not(.dropdown-toggle) is
 * (0,4,0) — it outranks .jkn-page .btn{border-radius:8px} (0,2,0) and
 * squares the inner corners, so these rendered as one segmented control.
 * Wrong signal: a segmented control means "pick one of these states", but
 * Edit / Delete / Test print are three independent verbs. Qualifying the
 * ancestor with its element name lifts this to (0,4,1) so it wins on
 * specificity rather than stylesheet order — the same discipline the
 * .card-header override above is written to.
 *
 * Scoped to .jkn-cell-actions, so settings/facility.blade.php's
 * identically-structured rows inherit the fix with no markup change.
 */

.jkn-page td.jkn-cell-actions .btn-group {
    align-items: center;
}

.jkn-page td.jkn-cell-actions .btn-group > .btn {
    border-radius: 8px;
    margin-left: 0;
}

.jkn-page td.jkn-cell-actions .btn-group > .btn + .btn {
    margin-left: .3rem;
}


/* Inside a table row the standard hover-lift reads as jitter — the row is
   only ~46px tall and three buttons bouncing 1px on mouse-over defeats the
   alignment the row depends on. Brightness and a tightened shadow carry the
   response instead. Resting shadows go too: btn-danger's red glow bleeds
   into the row below at this size. */
.jkn-page td.jkn-cell-actions .btn {
    box-shadow: none;
}

.jkn-page td.jkn-cell-actions .btn:hover {
    transform: none;
    box-shadow: 0 2px 6px -2px rgba(15, 23, 42, .18);
}

/* ---------- buttons: disabled ----------
 * The modal's Save is .prop('disabled', true) for the duration of an AJAX
 * save. CSS :hover still matches a disabled <button>, and Bootstrap only
 * applies pointer-events:none to .disabled on <a> — so mid-save the button
 * dimmed to .65 opacity and went on lifting and brightening under the
 * cursor. Two pseudo-classes put this at (0,4,0), clearing the (0,3,0)
 * hover rules above.
 */

.jkn-page .btn:disabled:hover,
.jkn-page .btn.disabled:hover {
    transform: none;
    filter: none;
    cursor: not-allowed;
}

/* ---------- buttons: focus ----------
 * Deliberately an outline, not a box-shadow. A shadow ring would land at
 * (0,3,0) — an exact tie with .jkn-page .btn-primary:focus above, resolved
 * only by source order. Nothing in bootstrap.min.css, adminlte.min.css or
 * this file sets `outline` on a button, so this composes with every
 * existing shadow instead of racing it.
 *
 * :focus-visible is Chrome 86+ / Firefox 85+. On anything older the whole
 * rule is dropped as an unknown selector and Bootstrap's own focus ring
 * remains — degraded, never absent.
 */

.jkn-page .btn:focus-visible {
    outline: 2px solid #3b5bdb;
    outline-offset: 2px;
}

.jkn-page .btn-default:focus,
.jkn-page .btn-secondary:focus,
.jkn-page .btn-outline-primary:focus {
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .18);
}

/* ---------- modal header dismiss ----------
 * Left as Bootstrap's &times; glyph rather than a Font Awesome icon: .close
 * is not a .btn, it already carries aria-label="Close" with aria-hidden on
 * the glyph, and swapping in fa-times would inherit .close's font-size and
 * text-shadow and need both overridden. Colour and hover are the parts
 * worth systemising.
 */

.jkn-page .modal-header .close {
    color: #94a3b8;
    text-shadow: none;
    opacity: 1;
    transition: color .15s ease;
}

.jkn-page .modal-header .close:hover {
    color: #1e293b;
    opacity: 1;
}

/* ---------- status chips ---------- */

.jkn-status-chip {
    display: inline-flex;
    align-items: center;
    padding: .6rem 1.1rem;
    border-radius: 999px;
    font-weight: 600;
    font-size: .85rem;
    margin-bottom: 1.1rem;
}

.jkn-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    margin-right: .55rem;
}

.jkn-status-on {
    background: #ecfdf5;
    color: #047857;
}

.jkn-status-on .jkn-status-dot {
    background: #10b981;
    box-shadow: 0 0 0 4px rgba(16, 185, 129, .18);
}

.jkn-status-off {
    background: #f1f5f9;
    color: #64748b;
}

.jkn-status-off .jkn-status-dot {
    background: #94a3b8;
}

/* ---------- source / info badges ---------- */

.jkn-source-badge {
    display: inline-flex;
    align-items: center;
    padding: .3rem .7rem;
    border-radius: 999px;
    font-weight: 600;
    font-size: .72rem;
    margin-bottom: .75rem;
}

.jkn-source-badge i {
    margin-right: .4rem;
}

.jkn-source-database {
    background: #ecfdf5;
    color: #047857;
}

.jkn-source-env {
    background: #f1f5f9;
    color: #64748b;
}

.jkn-page .card.card-secondary,
.jkn-page .card.card-outline.card-secondary {
    border-top: none;
}

.jkn-config-table {
    font-size: .85rem;
}

.jkn-config-table th {
    color: #64748b;
    font-weight: 600;
    width: 40%;
    border-top: none;
}

.jkn-config-table td {
    border-top: none;
}

/* Compact effective-config readout: 2-col grid instead of a tall table so
   the sidebar can sit flush with the Email (SMTP) card without page scroll. */
.jkn-config-grid {
    display: flex;
    flex-wrap: wrap;
    margin: -.35rem;
}

.jkn-config-cell {
    width: 50%;
    padding: .35rem;
    box-sizing: border-box;
    min-width: 0;
}

.jkn-config-cell-wide {
    width: 100%;
}

.jkn-config-cell-third {
    width: 33.333%;
}

.jkn-config-label {
    display: block;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #94a3b8;
    margin-bottom: .15rem;
}

.jkn-config-value {
    display: block;
    font-size: .85rem;
    font-weight: 600;
    color: #1e293b;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.jkn-config-cell-wide .jkn-config-value {
    white-space: normal;
    word-break: break-all;
}

/* Stacked sections inside a single sidebar panel: a hairline divider between
   consecutive sections (none above the first), so several groupings read as
   one clean card instead of several separate cards. */
.jkn-panel-section + .jkn-panel-section {
    margin-top: .85rem;
    padding-top: .85rem;
    border-top: 1px solid #eef1f5;
}

.jkn-panel-heading {
    font-weight: 700;
    font-size: .8rem;
    color: #1e293b;
    margin-bottom: .5rem;
}

/* ---------- modal polish ---------- */

.jkn-page .modal-content {
    border: none;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 24px 48px -12px rgba(15, 23, 42, .35);
}

.jkn-page .modal-header {
    background: #fff;
    border-bottom: 1px solid #eef1f5;
    align-items: center;
}

.jkn-page .modal-header .icon-badge {
    margin-right: .75rem;
}

.jkn-page .modal-header .modal-title {
    font-weight: 700;
    font-size: 1rem;
    color: #1e293b;
}

.jkn-page .modal-footer {
    border-top: 1px solid #eef1f5;
}

/* ---------- misc ---------- */

.jkn-page .form-label {
    font-weight: 600;
    font-size: .82rem;
    color: #334155;
}

.jkn-page .form-control {
    border-radius: 8px;
    border-color: #e2e8f0;
}

.jkn-page .form-control:focus {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

.jkn-page .card-help-block {
    background: #f8fafc;
    border-radius: 10px;
    padding: .9rem 1rem;
    font-size: .82rem;
    color: #64748b;
}

/* ---------- bento fit-to-screen layout ----------
 * .jkn-page is a flex column with a HARD (not min-) height bounded to the
 * viewport space actually free between the fixed navbar and fixed footer
 * (see .layout-navbar-fixed/.layout-footer-fixed rules in adminlte.css:
 * 3.5rem navbar + 3.5rem footer + the 10px content-wrapper top padding from
 * template.blade.php ≈ 7.75rem, rounded up to 8rem for safety) plus
 * overflow:hidden. A hard height (not min-height) is required for the
 * flex:1/min-height:0/overflow-y:auto chain below to actually contain
 * overflow internally instead of just growing the box — min-height only
 * sets a floor and lets the container expand past the viewport.
 *
 * Every flex ancestor between .jkn-page and the scrollable card body needs
 * min-height:0 too (flex items default to min-height:auto, which refuses to
 * shrink below content size and breaks the chain silently).
 *
 * Everything above .jkn-bento-main (page header, tabs, flash messages)
 * keeps its natural height; .jkn-bento-main absorbs the rest. If content is
 * ever taller than that on a very short viewport, only .jkn-fill-card's
 * body scrolls internally — the outer page never does.
 */

.jkn-page {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 8rem);
    overflow: hidden;
}

.jkn-bento-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
    flex-shrink: 0;
}

.jkn-stat-tile {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 10px 24px -16px rgba(15, 23, 42, .25);
    padding: 1rem 1.15rem;
    display: flex;
    align-items: center;
    /* IE11 doesn't support CSS Grid (above) or flex gap (icon/text below);
       .jkn-bento-stats silently falls back to block stacking there, so this
       margin gives the stacked tiles breathing room instead of touching. */
    margin-bottom: .75rem;
}

.jkn-stat-tile .icon-badge {
    margin-right: .85rem;
}

.jkn-stat-value {
    font-size: 1.5rem;
    font-weight: 800;
    color: #1e293b;
    line-height: 1;
}

.jkn-stat-label {
    font-size: .72rem;
    color: #64748b;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-top: .15rem;
}

.jkn-bento-main {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.jkn-bento-main > .row {
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-fill-col {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.jkn-fill-card {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-fill-card .card-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.jkn-fill-sidebar {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.jkn-fill-sidebar > .card {
    margin-bottom: 1rem;
}

.jkn-fill-sidebar > .card:last-child {
    margin-bottom: 0;
}

/* ---------- card footer ----------
 * Sits outside .jkn-fill-card's scrolling body, so a pager stays pinned to the
 * bottom of the card instead of scrolling away with the rows above it.
 */

.jkn-page .card-footer {
    background: #fff;
    border-top: 1px solid #eef1f5;
    border-radius: 0 0 14px 14px;
    padding: .7rem 1.15rem;
}

.jkn-fill-card > .card-footer {
    flex-shrink: 0;
}

.jkn-page .pagination {
    margin-bottom: 0;
}

.jkn-page .pagination .page-link {
    border: none;
    border-radius: 8px;
    margin-right: .25rem;
    padding: .3rem .65rem;
    color: #475569;
    font-weight: 600;
    font-size: .82rem;
}

.jkn-page .pagination .page-link:hover {
    background: #f1f5f9;
    color: #1e293b;
}

.jkn-page .pagination .page-item.active .page-link {
    background: linear-gradient(135deg, #60a5fa 0%, #3b5bdb 100%);
    color: #fff;
    box-shadow: 0 4px 12px -4px rgba(59, 91, 219, .55);
}

.jkn-page .pagination .page-item.disabled .page-link {
    background: transparent;
    color: #cbd5e1;
}

/* ---------- warning status chip ----------
 * The third chip state DESIGN.md leaves open ("if one is needed, follow the
 * same pill-plus-dot shape with the Amber pair"). The dot is accent-amber
 * (#f97316) itself; the surface and text are new warning-surface-* tokens,
 * added to DESIGN.md alongside the existing success-surface-* pair — chips are
 * flat, so they need their own tint/ink values rather than reusing the badge
 * gradient stops. -sm is the in-table size; the base .jkn-status-chip padding
 * is sized for a page-level banner.
 */

.jkn-status-warn {
    background: #fff7ed;
    color: #c2410c;
}

.jkn-status-warn .jkn-status-dot {
    background: #f97316;
    box-shadow: 0 0 0 4px rgba(249, 115, 22, .18);
}

.jkn-status-chip.jkn-status-chip-sm {
    padding: .2rem .6rem;
    font-size: .72rem;
    font-weight: 700;
    margin-bottom: 0;
}

/* ---------- danger status chip ----------
 * Fourth chip state, for hard failures: the client-measured
 * iqms.network.probe row on /home and "Down" services. Follows the
 * warning-chip precedent above — pill-plus-dot, flat, with new
 * danger-surface-* tokens added to DESIGN.md alongside the
 * success/warning surface pairs (danger/danger-light are the badge
 * gradient stops, not usable as a flat tint/ink pair).
 */

.jkn-status-bad {
    background: #fef2f2;
    color: #b91c1c;
}

.jkn-status-bad .jkn-status-dot {
    background: #ef4444;
    box-shadow: 0 0 0 4px rgba(239, 68, 68, .18);
}

/* ---------- flat info chips ----------
 * Flat, never gradient: per the Gradient-Means-Icon rule these carry
 * information, they are not actionable.
 */

.jkn-chip {
    display: inline-block;
    padding: .22rem .6rem;
    border-radius: 999px;
    background: #f1f5f9;
    color: #475569;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .02em;
    white-space: nowrap;
}

.jkn-chip i {
    margin-right: .35rem;
    color: #94a3b8;
}

/* Admin JKN role tag (admin/users/index.blade.php's Facilities column) —
   tinted with the page's own accent blue instead of the neutral .jkn-chip
   gray, since role is a state indicator (Admin vs Facility-Scoped), which
   the product register allows accent color for. Stays within the page's
   "one subsystem, one color" blue rather than introducing a new hue. */
.jkn-chip-admin {
    background: #eef2ff;
    color: #3b5bdb;
}

/* Stacks multiple facility chips vertically (one per line, like the old
   plain-text + <br> list it replaces) instead of .jkn-chip's default
   inline-block wrap. */
.jkn-chip-list {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.jkn-chip-list .jkn-chip {
    margin-bottom: .3rem;
}

.jkn-chip-list .jkn-chip:last-child {
    margin-bottom: 0;
}

.jkn-ip-chip {
    display: inline-block;
    padding: .18rem .5rem;
    margin: 0 .25rem .25rem 0;
    border-radius: 7px;
    background: #f1f5f9;
    color: #334155;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
}

/* ---------- facility listing ---------- */

.jkn-facility-toolbar {
    margin-bottom: 1rem;
}

.jkn-facility-toolbar .input-group-text {
    background: #f8fafc;
    border-color: #e2e8f0;
    border-right: none;
    border-radius: 8px 0 0 8px;
    color: #94a3b8;
}

.jkn-facility-toolbar .input-group > .form-control {
    border-left: none;
    border-radius: 0 8px 8px 0;
}

.jkn-facility-toolbar .jkn-clear-link {
    color: #64748b;
    font-weight: 600;
}

.jkn-facility-toolbar .jkn-clear-link:hover {
    color: #1e293b;
}

.jkn-result-count {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #94a3b8;
}

/* Rows here stack several lines per cell, so align to the top rather than the
   .jkn-page .table default of middle. */
.jkn-page .jkn-facility-table td {
    vertical-align: top;
}

.jkn-page .jkn-facility-table td.jkn-cell-index {
    color: #94a3b8;
    font-weight: 700;
    font-size: .82rem;
    padding-top: .95rem;
}

.jkn-facility-cell {
    display: flex;
    align-items: flex-start;
}

.jkn-facility-cell .icon-badge {
    margin-right: .7rem;
    margin-top: .1rem;
}

.jkn-cell-title {
    display: block;
    font-weight: 700;
    color: #1e293b;
    line-height: 1.3;
}

/* Name-column avatar (admin/users/index.blade.php) — flat tinted initial
   circle, not a gradient: Gradient-Means-Icon reserves gradients for icon
   badges/primary buttons/stat-tile icons, and a gradient repeated on every
   row would read as decoration, not an icon. */
.jkn-user-cell {
    display: flex;
    align-items: center;
}

.jkn-user-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #eef2ff;
    color: #3b5bdb;
    font-weight: 700;
    font-size: .82rem;
    margin-right: .7rem;
    flex-shrink: 0;
}

.jkn-cell-meta {
    display: block;
    font-size: .82rem;
    color: #64748b;
    line-height: 1.45;
}

.jkn-cell-meta i {
    display: inline-block;
    width: 13px;
    margin-right: .3rem;
    color: #cbd5e1;
}

.jkn-cell-counts {
    margin-top: .2rem;
    font-size: .72rem;
    font-weight: 600;
    color: #94a3b8;
}

/* Icon+count summary (Setup QMS Locations table's Devices column) — chips
   instead of "N registers · N services · ..." prose so a narrow column
   wraps between whole chips, not mid-phrase across seven single-word lines. */
/* Fixed layout so the <th style="width:%"> values in locations.blade.php
   are honored exactly, instead of table-layout:auto's default of shrinking
   unconstrained columns toward their content's narrowest wrappable word
   whenever DataTables' own (init-time, pre-AJAX-data) width calc leaves a
   column's <th> without a usable measurement. */
#locationsTable,
#usersTable,
#facilitiesTable {
    table-layout: fixed;
    width: 100%;
}

/* DataTables sets an inline pixel width at init — override so percentage
   column widths in the <thead> fill the card on directory screens. */
.jkn-page .jkn-dir-table {
    width: 100% !important;
}

.jkn-page .jkn-dir-card .dataTables_wrapper {
    width: 100%;
}

.jkn-device-chips {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem .55rem;
    margin-top: .15rem;
}

.jkn-device-chip {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    font-size: .72rem;
    font-weight: 600;
    color: #94a3b8;
    white-space: nowrap;
}

.jkn-device-chip i {
    color: #cbd5e1;
}

.jkn-cell-path {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
    font-size: .82rem;
    color: #334155;
}

.jkn-cell-muted {
    color: #cbd5e1;
}

.jkn-page .jkn-facility-table td.jkn-cell-actions {
    white-space: nowrap;
}

/* ---------- empty state ----------
 * Deliberately plain: an icon, one line of explanation, one action. No
 * illustration — this is an instrument panel, not a consumer app.
 */

.jkn-empty-state {
    text-align: center;
    padding: 2.5rem 1rem;
    color: #64748b;
}

.jkn-empty-state .icon-badge {
    margin-bottom: .9rem;
}

.jkn-empty-title {
    font-weight: 700;
    font-size: .95rem;
    color: #1e293b;
    margin-bottom: .25rem;
}

/* Long forms in a modal: scroll the body rather than the whole viewport, so
   the header and the save button stay reachable on a 768px-tall counter. */
.jkn-modal-scroll {
    max-height: 62vh;
    overflow-y: auto;
}

/* ---------- Add/Edit Location wizard ----------
 * Alternative to .jkn-modal-scroll above for the Location Add/Edit modals:
 * instead of scrolling one long form, the same fields are split into 3
 * short steps (see locations.blade.php) so the body never needs to scroll
 * at all. Step panes stay in the DOM and are toggled with .active (not
 * removed) so field values and native HTML5 validity survive Back/Next.
 *
 * Namespaced .jkn-loc-wizard-* rather than .jkn-wizard-* — that prefix is
 * already owned by the Third-Party QMS setup wizard's amber step-tabs
 * below (a different component, different subsystem color); reusing it
 * silently broke step-hiding here since both rules target the same class
 * with equal specificity.
 */
.jkn-loc-wizard-dialog {
    max-width: 560px;
}

.jkn-page .jkn-loc-wizard-nav {
    display: flex;
    align-items: flex-start;
    padding: 1.1rem 1.5rem .3rem;
}

.jkn-page .jkn-loc-wizard-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 auto;
}

.jkn-page .jkn-loc-wizard-nav-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: #eef1f5;
    color: #94a3b8;
    font-size: .78rem;
    font-weight: 700;
    flex-shrink: 0;
    transition: background-color .15s ease, color .15s ease;
}

.jkn-page .jkn-loc-wizard-nav-label {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: #94a3b8;
    margin-top: .35rem;
    white-space: nowrap;
    transition: color .15s ease;
}

.jkn-page .jkn-loc-wizard-nav-item.active .jkn-loc-wizard-nav-circle,
.jkn-page .jkn-loc-wizard-nav-item.done .jkn-loc-wizard-nav-circle {
    /* Verbatim from .icon-badge-purple above, not a new gradient value. */
    background: linear-gradient(135deg, #c084fc 0%, #7c3aed 100%);
    color: #fff;
    box-shadow: 0 6px 14px -5px rgba(124, 58, 237, .55);
}

.jkn-page .jkn-loc-wizard-nav-item.active .jkn-loc-wizard-nav-label {
    color: #3b5bdb;
}

.jkn-page .jkn-loc-wizard-nav-item.done .jkn-loc-wizard-nav-label {
    color: #475569;
}

.jkn-page .jkn-loc-wizard-nav-line {
    flex: 1 1 auto;
    height: 2px;
    background: #e2e8f0;
    margin: 13px .5rem 0;
    transition: background-color .15s ease;
}

.jkn-page .jkn-loc-wizard-nav-line.done {
    background: #7c3aed;
}

.jkn-loc-wizard-body {
    padding-top: .6rem;
}

.jkn-loc-wizard-step {
    display: none;
}

.jkn-loc-wizard-step.active {
    display: block;
    animation: jknLocWizardStepIn .15s ease;
}

@keyframes jknLocWizardStepIn {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ---------- drag-and-drop file zone ----------
 * Structurally the same composition as .jkn-empty-state (icon-badge, bold
 * title, one hint line, one action) — a flat surface, not a gradient: per
 * "Gradient-Means-Icon" a dropzone is information/affordance, not itself
 * actionable, so only its Browse/Import buttons may carry the brand
 * gradient. .jkn-dropzone-js is added by feature-detecting JS only — the
 * raw <input type=file> underneath renders as a normal visible control
 * (under the Browse button) until then, so drag-and-drop degrades to a
 * plain file picker on any browser without full HTML5 DnD support.
 */
.jkn-page .jkn-dropzone {
    position: relative;
    text-align: center;
    padding: 1.75rem 1rem;
    border: 2px dashed #e2e8f0;
    border-radius: 11px;
    background: #f8fafc;
    transition: border-color .15s ease, background-color .15s ease;
}

.jkn-page .jkn-dropzone .icon-badge {
    margin-bottom: .75rem;
}

.jkn-page .jkn-dropzone-title {
    font-weight: 700;
    font-size: .95rem;
    color: #1e293b;
    margin-bottom: .25rem;
}

.jkn-page .jkn-dropzone-hint {
    font-size: .82rem;
    color: #64748b;
    margin-bottom: .9rem;
}

.jkn-page .jkn-dropzone.is-dragover {
    border-color: #3b5bdb;
    background: #eef2ff;
}

.jkn-page .jkn-dropzone.has-file {
    border-style: solid;
    border-color: #c7d2fe;
}

.jkn-page .jkn-dropzone-file {
    margin-top: .75rem;
}

.jkn-page .jkn-dropzone.jkn-dropzone-js .jkn-dropzone-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}

/* ---------- Setup QMS: facility picker (centered card) ----------
 * Mirrors the "centered chooser" pattern used elsewhere in the app (e.g.
 * Reports' "Pilih PTJ" screen): a single card floats in the middle of the
 * available viewport rather than sitting flush at the top of the page.
 * .jkn-qms-picker-wrap is the flex-centering shell; .jkn-page already
 * bounds the page to the viewport, so this needs no scroll handling of its
 * own — the card simply can't be taller than the space .jkn-page reserves.
 */

.jkn-qms-picker-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-qms-picker-card {
    max-width: 560px;
    width: 100%;
    text-align: center;
}

.jkn-page .jkn-qms-picker-card.card {
    margin-bottom: 0;
}

.jkn-qms-picker-card .card-body {
    padding: 2.5rem 2.25rem;
}

.jkn-qms-picker-badge {
    margin: 0 auto 1.25rem;
}

.jkn-qms-picker-title {
    font-weight: 700;
    font-size: 1.25rem;
    color: #1e293b;
    margin-bottom: .4rem;
}

.jkn-qms-picker-sub {
    color: #64748b;
    font-size: .875rem;
    margin-bottom: 1.75rem;
}

.jkn-qms-picker-form {
    text-align: left;
}

.jkn-qms-picker-label {
    display: block;
    font-weight: 700;
    font-size: .82rem;
    color: #3b5bdb;
    margin-bottom: .5rem;
}

.jkn-qms-picker-label i {
    margin-right: .4rem;
}

/* A leading search icon overlaid on the select2-bootstrap box: the icon is
   a sibling positioned absolutely over the rendered selection, with
   pointer-events:none so clicks pass through to select2's own control
   underneath and still open the dropdown. */
.jkn-search-select {
    position: relative;
}

.jkn-search-select-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: #94a3b8;
    z-index: 1;
    pointer-events: none;
}

.jkn-search-select .select2-container .select2-selection--single {
    height: calc(1.5em + .75rem + 2px);
    border-radius: 8px;
    border-color: #e2e8f0;
}

.jkn-search-select .select2-container .select2-selection--single:focus,
.jkn-search-select .select2-container--focus .select2-selection--single {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

.jkn-search-select .select2-container .select2-selection__rendered {
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    transform: translateY(-50%);
    margin: 0;
    padding-left: 2.25rem;
    line-height: normal;
}

.jkn-search-select .select2-container .select2-selection__arrow {
    height: calc(1.5em + .75rem + 2px);
}

/* Grouped, icon-annotated results list for the facility picker's select2
   dropdown (see settings/qms.blade.php's templateResult) — a type icon plus
   a muted type subtitle per row, so Hospital / Klinik Kesihatan / Klinik
   Pergigian read apart at a glance in a long, alphabetically-mixed list.
   Icons stay neutral slate rather than picking up a new hue: DESIGN.md's
   "One Subsystem, One Color" rule already spends purple on this whole page. */
.jkn-facility-option {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .05rem 0;
}

.jkn-facility-option-icon {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 7px;
    background: #f1f5f9;
    color: #64748b;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .82rem;
}

/* The select2-bootstrap theme flips the whole highlighted row to a solid
   blue background with white text — a light indigo-on-indigo chip (the
   resting state) washes out against that same blue, so the highlighted
   icon instead goes translucent-white-on-blue, matching the row's own
   white text color rather than introducing a new hue. */
.select2-results__option--highlighted .jkn-facility-option-icon {
    background: rgba(255, 255, 255, .2);
    color: #fff;
}

.jkn-facility-option-text {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    min-width: 0;
}

.jkn-facility-option-name {
    font-weight: 600;
    font-size: .875rem;
    color: #1e293b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-facility-option-type {
    font-size: .72rem;
    color: #94a3b8;
}

.jkn-qms-picker-hint {
    text-align: center;
    color: #94a3b8;
    font-size: .82rem;
    margin: 1rem 0 0;
}

.jkn-qms-picker-hint i {
    margin-right: .3rem;
}

.jkn-days-checks {
    display: flex;
    flex-wrap: wrap;
}

.jkn-day-check {
    display: inline-block;
    font-weight: 400;
    font-size: .85rem;
    color: #334155;
    margin: 0 1rem .35rem 0;
    cursor: pointer;
}

.jkn-day-check input {
    margin-right: .3rem;
}

/* ---------- Setup QMS: location settings modal ----------
 * Wide modal: a left rail (section nav + the firewall/VDI info callouts)
 * and a right content pane holding all seven entity sections. Sections and
 * their list/form views are toggled with .jkn-lm-hidden rather than
 * jQuery show()/hide() (which resets to display:block) because every one
 * of them is itself a flex column — losing display:flex breaks the same
 * min-height:0 scroll chain the bento layout above depends on.
 */

.jkn-lm-dialog {
    max-width: 1100px;
    width: calc(100vw - 3rem);
    margin-left: auto;
    margin-right: auto;
}

/* Debug modal: same 1100px footprint as the location-settings modal, but
   without the fixed modal-content height below — its two panels size
   naturally and the body scrolls via .jkn-modal-scroll instead of the
   rail/content flex chain. */
.jkn-debug-dialog {
    max-width: 1100px;
    width: calc(100vw - 3rem);
    margin-left: auto;
    margin-right: auto;
}

.jkn-page .jkn-lm-dialog .modal-content {
    height: calc(100vh - 7rem);
    display: flex;
    flex-direction: column;
}

.jkn-lm-title-sep {
    color: #cbd5e1;
    margin: 0 .35rem;
    font-weight: 400;
}

.jkn-lm-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    padding: 0;
}

.jkn-lm-rail {
    flex: 0 0 240px;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow-y: auto;
    background: #f8fafc;
    border-right: 1px solid #eef1f5;
    padding: .9rem;
}

.jkn-lm-rail-nav {
    flex-shrink: 0;
}

.jkn-lm-rail-item {
    display: block;
    border-radius: 8px;
    padding: .55rem .7rem;
    margin-bottom: .15rem;
    color: #475569;
    font-weight: 600;
    font-size: .85rem;
    transition: background-color .1s ease, color .1s ease;
}

.jkn-lm-rail-item:hover {
    background: #f1f5f9;
    color: #1e293b;
    text-decoration: none;
}

.jkn-lm-rail-item.active {
    background: #fff;
    color: #3b5bdb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

.jkn-lm-rail-item i {
    display: inline-block;
    width: 18px;
    margin-right: .5rem;
    text-align: center;
    color: #94a3b8;
}

.jkn-lm-rail-item.active i {
    color: #3b5bdb;
}

.jkn-lm-rail-count {
    float: right;
    margin-top: .05rem;
}

/* Pins the info callouts to the bottom of the rail when the nav is short;
   degrades to sitting directly below the nav on a rail tall enough that
   flex has nothing left to distribute — still correct, just not pinned. */
.jkn-lm-rail-info {
    margin-top: auto;
    padding-top: 1rem;
    flex-shrink: 0;
}

.jkn-lm-rail-info .jkn-warn-block + .jkn-warn-block {
    margin-top: .6rem;
}

.jkn-warn-block {
    background: #fff7ed;
    color: #c2410c;
    border-radius: 10px;
    padding: .75rem .85rem;
    font-size: .82rem;
    line-height: 1.5;
}

/* Direct child only. A descendant selector here ties on specificity with
   .jkn-page .btn > i and wins on source order, which painted the arrow on
   the "Set up a printer first" button inside this block orange with the
   wrong margin. The block's own icons are all direct children, so scoping
   is a no-op for them. */
.jkn-warn-block > i {
    color: #f97316;
    margin-right: .35rem;
}

.jkn-warn-block a {
    color: #c2410c;
    text-decoration: underline;
    font-weight: 600;
}

.jkn-lm-content {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 1rem 1.25rem;
    overflow: hidden;
}

.jkn-lm-alerts {
    flex-shrink: 0;
}

.jkn-lm-alerts .alert {
    margin-bottom: .75rem;
}

.jkn-lm-section {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-lm-view {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-lm-hidden {
    display: none !important;
}

.jkn-lm-pane-header {
    display: flex;
    align-items: flex-start;
    border-bottom: 1px solid #eef1f5;
    padding-bottom: .75rem;
    margin-bottom: .75rem;
    flex-shrink: 0;
}

.jkn-lm-pane-title {
    font-weight: 700;
    font-size: .95rem;
    color: #1e293b;
}

.jkn-lm-pane-sub {
    font-size: .82rem;
    color: #64748b;
    margin-top: .1rem;
}

.jkn-lm-table-wrap {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.jkn-lm-form-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* The bento grid's negative gutter margins poke past this box's edges;
       without this the pane grows a horizontal scrollbar. The clipped strip
       is only the outermost cells' own padding — nothing visible. */
    overflow-x: hidden;
    padding-right: .25rem;
}

.jkn-lm-form-scroll .row + .jkn-panel-section,
.jkn-lm-form-scroll .jkn-panel-section + .jkn-panel-section {
    margin-top: .85rem;
    padding-top: .85rem;
    border-top: 1px solid #eef1f5;
}

/* ---------- Setup QMS: AJAX sections wrapper + bento form tiles ----------
 * jknLmSections is the swap target for the no-reload refresh: its inner HTML
 * is replaced wholesale after every AJAX mutation. It sits between
 * .jkn-lm-content (flex column) and the seven .jkn-lm-section children, so
 * it must be a transparent flex pass-through — without this the sections
 * lose their flex-grow/min-height:0 chain (the documented bento trap above)
 * and the internal table/form scrolling silently breaks.
 */

#jknLmSections {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Bento form layout: flex-wrap with negative-margin gutters (the
   .jkn-config-grid pattern — no flex gap, IE-safe). Cells are themselves
   flex so paired half-width tiles stretch to equal height per row. */

.jkn-lm-form-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    margin: -.4rem;
}

.jkn-lm-form-cell {
    width: 50%;
    padding: .4rem;
    box-sizing: border-box;
    min-width: 0;
    display: flex;
}

.jkn-lm-form-cell-wide {
    width: 100%;
}

@media (max-width: 991px) {
    .jkn-lm-form-cell {
        width: 100%;
    }
}

.jkn-lm-form-tile {
    flex: 1 1 auto;
    background: #f8fafc;
    border: 1px solid #eef1f5;
    border-radius: 10px;
    padding: .9rem 1rem;
}

.jkn-lm-form-tile .jkn-panel-heading {
    margin-bottom: .75rem;
}

/* The help block's resting background is the same #f8fafc as the tile it
   now sits on — flip it to white so it stays visible. */
.jkn-lm-form-tile .card-help-block {
    background: #fff;
}

/* Inline validation errors for the AJAX save path. Rendered by JS (as
   .alert.alert-danger, which supplies the colors — no new palette values
   here) between the pane header and the scrolling form so the block stays
   visible without scrolling. */
.jkn-lm-form-errors {
    flex-shrink: 0;
    border-radius: 8px;
    font-size: .82rem;
    margin-bottom: .75rem;
}

.jkn-lm-form-errors ul {
    margin: 0;
    padding-left: 1.1rem;
}

/* ---------- Third Party QMS: Add/Edit wizard ----------
 * Scoped under .jkn-wizard so these rules never touch the plain
 * .jkn-lm-form-grid layout still used by Setup QMS. Amber matches this
 * page's "external-boundary" hue (DESIGN.md); gradient stops copied
 * verbatim from .icon-badge-amber above, not a new value. No flex gap
 * (margins instead) and no CSS custom properties — Win7/IE11 counters. */

.jkn-wizard-steps {
    display: flex;
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
}

.jkn-wizard-steps li {
    flex: 1 1 0;
    min-width: 0;
}

.jkn-wizard-step {
    display: block;
    width: 100%;
    background: none;
    border: 0;
    border-bottom: 3px solid #eef1f5;
    padding: 0 .3rem .6rem;
    text-align: center;
    color: #64748b;
    font-size: .82rem;
    cursor: pointer;
}

.jkn-wizard-step[disabled] {
    opacity: .5;
    cursor: default;
}

.jkn-wizard-step-num {
    display: inline-block;
    width: 22px;
    height: 22px;
    line-height: 22px;
    border-radius: 50%;
    background: #eef1f5;
    color: #64748b;
    font-weight: 700;
    margin-right: .4rem;
}

.jkn-wizard-step-label {
    display: inline-block;
    vertical-align: middle;
}

.jkn-wizard-step-active {
    border-bottom-color: #f97316;
    color: #1e293b;
}

.jkn-wizard-step-active .jkn-wizard-step-num {
    background: linear-gradient(135deg, #fcd34d 0%, #f97316 100%);
    color: #fff;
}

.jkn-wizard-step-done .jkn-wizard-step-num {
    background: #fff7ed;
    color: #c2410c;
}

.jkn-wizard-step-done .jkn-wizard-step-label {
    color: #475569;
}

.jkn-wizard .jkn-lm-form-cell {
    width: 100%;
    display: none;
}

.jkn-wizard .jkn-lm-form-cell.jkn-wizard-pane-active {
    display: flex;
}

.jkn-wizard-check-error {
    font-size: .82rem;
    margin-top: .4rem;
}

/* ---------- Caller Officers panel (Setup QMS sidebar) ----------
 * Plain list rows, deliberately NOT a DataTable: the panel's subtree is
 * replaced wholesale by the AJAX refresh, and swapping rows under an
 * initialized DataTable desyncs it. Officers per facility are few, so no
 * search/pagination is needed. */

.jkn-page .jkn-officer-add {
    display: flex;
    gap: .5rem;
    margin-bottom: .85rem;
}

.jkn-page .jkn-officer-add .form-control {
    flex: 1;
    min-width: 0;
}

.jkn-page .jkn-officer-errors {
    border-radius: 8px;
    font-size: .82rem;
    padding: .5rem .75rem;
    margin-bottom: .75rem;
}

.jkn-page .jkn-officer-row {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .55rem .35rem;
    border-bottom: 1px solid #f1f5f9;
}

.jkn-page .jkn-officer-row:last-child {
    border-bottom: 0;
}

.jkn-page .jkn-officer-row:hover {
    background: #f8fafc;
}

.jkn-page .jkn-officer-main {
    flex: 1;
    min-width: 0;
}

.jkn-page .jkn-officer-name {
    display: block;
    font-weight: 600;
    font-size: .9rem;
    color: #1e293b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-page .jkn-officer-meta {
    display: block;
    font-size: .72rem;
    color: #94a3b8;
    white-space: nowrap;
}

/* The status chip doubles as the enable/disable toggle, so it's a <button>
   on this panel — undo the UA button chrome and add a press affordance. */
.jkn-page button.jkn-status-chip {
    border: 0;
    font-family: inherit;
    cursor: pointer;
    transition: box-shadow .12s ease-out, transform .12s ease-out;
}

.jkn-page button.jkn-status-chip:hover {
    box-shadow: 0 0 0 3px rgba(8, 145, 178, .18);
}

.jkn-page button.jkn-status-chip:active {
    transform: scale(.96);
}

.jkn-page button.jkn-status-chip:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(8, 145, 178, .3);
}

.jkn-page button.jkn-status-chip[disabled] {
    cursor: wait;
    opacity: .6;
}

.jkn-page .jkn-officer-empty {
    padding: 1.75rem .5rem;
}

/* Row transitions for the AJAX refresh: new rows slide-fade in, the row
   just saved flashes teal so the eye lands on what changed. */
@keyframes jknRowIn {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
}

.jkn-page .jkn-row-in {
    animation: jknRowIn .25s ease-out;
}

@keyframes jknRowFlash {
    0% { background-color: #ccfbf1; }
    100% { background-color: transparent; }
}

.jkn-page .jkn-row-flash {
    animation: jknRowFlash 1.1s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .jkn-page .jkn-row-in,
    .jkn-page .jkn-row-flash {
        animation: none;
    }

    .jkn-page button.jkn-status-chip,
    .jkn-page button.jkn-status-chip:active {
        transition: none;
        transform: none;
    }
}

/* ---------- SMTP diagnostic transcript ----------
 * The raw SMTP banner/EHLO exchange or redacted send-failure transcript on
 * the email settings page. No monospace anywhere in this system (see
 * DESIGN.md Typography), so this stays on the body font — just smaller,
 * pre-wrapped, and set on the Surface Hover tint so it reads as inset detail
 * rather than prose.
 */
.jkn-diag-transcript-toggle {
    font-size: .72rem;
    font-weight: 600;
    color: #64748b;
    cursor: pointer;
}

.jkn-diag-transcript {
    margin-top: .4rem;
    padding: .6rem .75rem;
    background: #f8fafc;
    border: 1px solid #eef1f5;
    border-radius: 8px;
    font-size: .82rem;
    line-height: 1.5;
    color: #334155;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ---------- auth pages (login) ----------
 * The login page has no authenticated shell (no navbar/sidebar/footer), so
 * it doesn't use .jkn-page. Instead these rules extend the same tokens
 * (gradient primary button, soft card shadow, indigo focus ring, icon
 * badge) onto AdminLTE's own auth-page classes (.login-page/.login-box/
 * .login-logo/.login-card-body), so the highest-traffic page in the app
 * carries the same visual system as everywhere else.
 */

.login-page {
    background-color: #1e293b;
}

.login-logo {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 1.25rem;
}

.login-logo .icon-badge {
    margin-bottom: .75rem;
}

.login-logo a {
    color: #fff;
    font-size: 1.25rem;
}

.login-logo-subtitle {
    color: rgba(255, 255, 255, .65);
    font-size: .875rem;
    margin-top: .15rem;
}

.login-box .card {
    border: none;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 20px 40px -20px rgba(15, 23, 42, .5);
}

.login-card-body {
    border-radius: 14px;
    padding: 1.5rem;
}

.login-card-body .form-control {
    border-radius: 8px;
    border-color: #e2e8f0;
}

.login-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text {
    border-color: #93c5fd;
}

.login-card-body .form-control:focus {
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

.login-card-body .btn-primary {
    background: linear-gradient(135deg, #60a5fa 0%, #3b5bdb 100%);
    border: none;
    border-radius: 8px;
    font-weight: 600;
    box-shadow: 0 4px 12px -4px rgba(59, 91, 219, .55);
    transition: all .15s ease;
}

.login-card-body .btn-primary:hover,
.login-card-body .btn-primary:focus {
    filter: brightness(1.06);
    box-shadow: 0 6px 16px -4px rgba(59, 91, 219, .65);
}

.login-secondary-links {
    text-align: center;
    margin-top: 1rem;
    font-size: .875rem;
    color: rgba(255, 255, 255, .7);
}

.login-secondary-links a {
    color: #fff;
    font-weight: 600;
}

.login-secondary-links .sep {
    margin: 0 .5rem;
    opacity: .5;
}

.login-page .modal-content {
    border: none;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 24px 48px -12px rgba(15, 23, 42, .35);
}

/* ---------- Workflow editor (Kaunter Bersepadu) ----------
 * The flow preview draws entry → vital sign → destinations as station
 * cards connected by a JS-drawn SVG overlay (animated beam), matching the
 * excalidraw the routing was designed from. Violet family — workflows are
 * Setup-QMS configuration (One Subsystem, One Color). The arrow glyphs stay
 * in the markup as the no-JS / old-browser / wrapped-row fallback — see
 * .jkn-wf-flow-svg below. */

.jkn-page .jkn-wf-board {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.jkn-page .jkn-wf-canvas {
    background: #f1f5f9;
    border-radius: 11px;
    padding: 1.15rem 1rem 1.2rem;
    overflow-x: auto;
}

.jkn-page .jkn-wf-flow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-wrap: nowrap;
    min-width: 100%;
    padding: .5rem .25rem;
    position: relative;
    box-sizing: border-box;
    vertical-align: top;
}

.jkn-page .jkn-wf-node {
    display: flex;
    align-items: flex-start;
    min-width: 148px;
    max-width: 200px;
    padding: .7rem .8rem;
    border: 1px solid #e2e8f0;
    border-radius: 11px;
    background: #fff;
    margin: .3rem 0;
    position: relative;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}

.jkn-page .jkn-wf-node-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: #f1f5f9;
    color: #64748b;
    font-size: .78rem;
    margin-right: .65rem;
}

.jkn-page .jkn-wf-node-body {
    min-width: 0;
    flex: 1 1 auto;
}

.jkn-page .jkn-wf-node-kicker {
    display: block;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #64748b;
}

.jkn-page .jkn-wf-node-title {
    display: block;
    max-width: 140px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 700;
    font-size: .875rem;
    color: #1e293b;
}

.jkn-page .jkn-wf-node-sub {
    display: block;
    max-width: 140px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: .72rem;
    color: #64748b;
    margin-top: 2px;
}

.jkn-page .jkn-wf-node-entry {
    border-color: #c084fc;
    background: #f5f3ff;
}

.jkn-page .jkn-wf-node-entry .jkn-wf-node-icon {
    background: #ede9fe;
    color: #7c3aed;
}

.jkn-page .jkn-wf-node-vs {
    border-color: #cbd5e1;
    background: #f8fafc;
}

.jkn-page .jkn-wf-node-vs .jkn-wf-node-icon {
    background: #e2e8f0;
    color: #475569;
}

.jkn-page .jkn-wf-node-return .jkn-wf-node-icon {
    background: #ede9fe;
    color: #7c3aed;
}

/* Skipped destination — same neutral as the vital-sign node (One
 * Subsystem, One Color) with a dashed border to read as "bypassed". */
.jkn-page .jkn-wf-node-skip {
    border-style: dashed;
    border-color: #cbd5e1;
    background: #f8fafc;
}

.jkn-page .jkn-wf-arrow {
    margin: 0 .7rem;
    color: #94a3b8;
    font-size: .95rem;
}

.jkn-page .jkn-wf-dests {
    display: inline-block;
    vertical-align: middle;
}

.jkn-page .jkn-wf-col-label {
    display: block;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #64748b;
    margin: 0 0 .35rem .15rem;
}

.jkn-page .jkn-wf-dests .jkn-wf-node {
    display: flex;
}

/* Lane separator: skipped destinations sort last, so the first skip node
 * after a non-skip one marks the boundary between the through-Tanda-Vital
 * lane and the bypass lane. */
.jkn-page .jkn-wf-dests .jkn-wf-node:not(.jkn-wf-node-skip) + .jkn-wf-node-skip {
    margin-top: .85rem;
}

/* Bypass lane: a flow containing skip-Tanda-Vital destinations reserves
 * room below for the shared rail that runs under Tanda Vital into Return. */
.jkn-page .jkn-wf-flow-bypass {
    padding-bottom: 2.5rem;
}

.jkn-page .jkn-wf-card .card-header {
    flex-wrap: wrap;
}

.jkn-page .jkn-wf-card-heading {
    min-width: 0;
    flex: 1 1 auto;
}

.jkn-page .jkn-wf-card .card-header .card-title-text {
    display: block;
    font-size: .95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-page .jkn-wf-card-meta {
    display: block;
    margin-top: .3rem;
}

.jkn-page .jkn-wf-card-meta .jkn-chip {
    margin: 0 .35rem .15rem 0;
}

.jkn-page .jkn-wf-card-actions {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin-left: auto;
}

.jkn-page .jkn-wf-card-actions .btn.jkn-btn-icon {
    box-shadow: none;
}

.jkn-page .jkn-wf-card-actions .btn.jkn-btn-icon:hover {
    transform: none;
}

.jkn-page .jkn-wf-vs-fields {
    background: #f8fafc;
    border: 1px solid #eef1f5;
    border-radius: 10px;
    padding: .75rem .9rem;
    margin-top: .75rem;
}

/* Animated beam connectors: JS-drawn SVG overlay per .jkn-wf-flow. The
 * arrow glyphs stay in the markup as the no-JS / old-browser / wrapped-row
 * fallback and are only visibility-hidden (their margins keep the gap the
 * beam draws through). Flat violet pulse on a flat gray line — the
 * Gradient-Means-Icon rule keeps gradients off connectors. The dash's
 * resting stroke-dashoffset equals its dash length, so where SVG stroke
 * animation doesn't run (IE10/11) the pulse is simply never visible and
 * only the static line shows. */
.jkn-page .jkn-wf-beam-svg {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
}

.jkn-page .jkn-wf-flow-svg .jkn-wf-arrow {
    visibility: hidden;
}

.jkn-page .jkn-wf-beam-glow {
    fill: none;
    stroke: #c084fc;
    stroke-width: 6;
    stroke-linecap: round;
    opacity: .18;
}

.jkn-page .jkn-wf-beam-base {
    fill: none;
    stroke: #cbd5e1;
    stroke-width: 2;
    stroke-linecap: round;
}

.jkn-page .jkn-wf-beam-head {
    fill: #7c3aed;
}

/* After-mode skip rail and VS→Return rail: matching dashed slate
 * connectors with a violet pulse and arrowhead. */
.jkn-page .jkn-wf-beam-bypass-glow {
    fill: none;
    stroke: #c084fc;
    stroke-width: 6;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .12;
}

.jkn-page .jkn-wf-beam-bypass-base {
    fill: none;
    stroke: #94a3b8;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 5 4;
}

.jkn-page .jkn-wf-beam-bypass-dash {
    fill: none;
    stroke: #7c3aed;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 16 200;
    stroke-dashoffset: 16;
    animation: jknWfBeam 2.6s linear infinite;
}

.jkn-page .jkn-wf-beam-bypass-head {
    fill: #7c3aed;
}

/* pathLength="100" normalizes every path; dash = 16 units, gap 200 keeps a
 * single pulse per path. 0..78% travels start->end, 78..100% rests. */
@keyframes jknWfBeam {
    0%   { stroke-dashoffset: 16; }
    78%  { stroke-dashoffset: -100; }
    100% { stroke-dashoffset: -100; }
}

.jkn-page .jkn-wf-beam-dash {
    fill: none;
    stroke: #7c3aed;
    stroke-width: 2.25;
    stroke-linecap: round;
    stroke-dasharray: 16 200;
    stroke-dashoffset: 16;
    animation: jknWfBeam 2.6s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .jkn-page .jkn-wf-beam-dash,
    .jkn-page .jkn-wf-beam-bypass-dash {
        animation: none;
    }
}

/* ---------- Workflow editor: Add/Edit modal ----------
 * Bounded wizard: desktop content must fit without a modal scrollbar.
 * Short/mobile viewports keep overflow as a safety net so fields stay
 * reachable. Flat violet states only (One Subsystem, One Color);
 * gradients stay on the header badge and Save button. Selected/focus
 * states are :checked/:focus + sibling (IE9+) or a JS class — no
 * :has()/:focus-within on the Windows-7 floor. */

.jkn-page .jkn-wf-dialog {
    max-width: 980px;
    width: calc(100vw - 3rem);
    margin-left: auto;
    margin-right: auto;
}

.jkn-page #modalWorkflow {
    overflow: hidden;
}

body.modal-open .jkn-page .jkn-bento-main,
body.modal-open .jkn-page .jkn-wf-board {
    overflow: hidden;
}

.jkn-page .jkn-wf-dialog .modal-content {
    max-height: calc(100vh - 6rem);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.jkn-page .jkn-wf-dialog form {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-page .jkn-wf-dialog .modal-header,
.jkn-page .jkn-wf-dialog .modal-footer {
    flex-shrink: 0;
}

.jkn-page .jkn-wf-dialog .modal-header {
    padding: .75rem 1.15rem;
}

.jkn-page .jkn-wf-footer {
    padding: .7rem 1.15rem;
}

@media (max-width: 767px) {
    .jkn-page .jkn-wf-dialog .modal-content {
        max-height: calc(100vh - 2.5rem);
    }

    .jkn-page .jkn-wf-node {
        min-width: 148px;
    }

    .jkn-page .jkn-wf-arrow {
        margin: 0 .7rem;
    }
}

.jkn-page .jkn-wf-modal-heading {
    min-width: 0;
    margin-right: auto;
}

.jkn-page .jkn-wf-modal-heading .modal-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-page .jkn-wf-modal-sub {
    font-size: .78rem;
    color: #64748b;
    margin-top: .1rem;
}

.jkn-page .jkn-wf-editor {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 0;
}

.jkn-page .jkn-wf-editor-form {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: .85rem 1.15rem 0;
}

/* Numbered step bar, full width and evenly split — same sunken-track /
   white-active-pill vocabulary as the page-level .nav-tabs component, sized
   for a 4-step wizard instead of top-level page tabs. Plain <ol>/<li>, no
   list-style/padding reset dependency on anything newer than CSS2.1. */
.jkn-page .jkn-wf-steps {
    display: flex;
    flex-shrink: 0;
    width: 100%;
    margin: 0 0 .7rem;
    padding: .25rem;
    list-style: none;
    background: #f1f5f9;
    border-radius: 10px;
}

.jkn-page .jkn-wf-step-item {
    flex: 1 1 0;
    min-width: 0;
    margin: 0 .15rem;
}

.jkn-page .jkn-wf-step-item:first-child {
    margin-left: 0;
}

.jkn-page .jkn-wf-step-item:last-child {
    margin-right: 0;
}

.jkn-page .jkn-wf-step {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: .4rem .5rem;
    border-radius: 8px;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
    font-size: .82rem;
    color: #475569;
    transition: all .15s ease;
}

.jkn-page .jkn-wf-step:hover {
    color: #1e293b;
}

.jkn-page .jkn-wf-step.active {
    background: #fff;
    color: #3b5bdb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

.jkn-page .jkn-wf-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin-right: .35rem;
    border-radius: 999px;
    background: #e2e8f0;
    color: #64748b;
    font-size: .7rem;
    font-weight: 700;
    line-height: 1;
    vertical-align: middle;
}

.jkn-page .jkn-wf-step.active .jkn-wf-step-num {
    background: #3b5bdb;
    color: #fff;
}

.jkn-page .jkn-wf-step-num-check {
    display: none;
}

.jkn-page .jkn-wf-step-done .jkn-wf-step-num {
    background: #ecfdf5;
    color: #047857;
}

.jkn-page .jkn-wf-step-done .jkn-wf-step-num-digit {
    display: none;
}

.jkn-page .jkn-wf-step-done .jkn-wf-step-num-check {
    display: inline;
}

.jkn-wf-tab-count {
    display: inline-block;
    min-width: 1.1rem;
    margin-left: .3rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    background: #f1f5f9;
    color: #475569;
    font-size: .68rem;
    font-weight: 700;
    line-height: 1.4;
}

.jkn-page .jkn-wf-step.active .jkn-wf-tab-count {
    background: rgba(59, 91, 219, .12);
    color: #3b5bdb;
}

@media (max-width: 767px) {
    .jkn-page .jkn-wf-step-label {
        display: none;
    }

    .jkn-page .jkn-wf-step-num {
        margin-right: 0;
    }
}

.jkn-page .jkn-wf-tab-content {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding-bottom: .85rem;
}

.jkn-page .jkn-wf-tab-content > .tab-pane.active {
    display: flex;
    flex-direction: column;
    width: 100%;
}

.jkn-page .jkn-wf-tab-content > #wfPaneBasics.active,
.jkn-page .jkn-wf-tab-content > #wfPaneVital.active {
    flex: 0 0 auto;
    overflow: visible;
}

.jkn-page .jkn-wf-tab-content > #wfPaneDest.active,
.jkn-page .jkn-wf-tab-content > #wfPaneReview.active {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.jkn-wf-pane-hint {
    color: #64748b;
    font-size: .82rem;
    margin-bottom: .65rem;
    flex-shrink: 0;
}

.jkn-wf-step-error {
    color: #b91c1c;
    font-size: .82rem;
    margin: .45rem 0 0;
    flex-shrink: 0;
}

.jkn-page .jkn-wf-basics-grid {
    display: block;
    width: 100%;
    margin: 0 0 .35rem;
}

.jkn-page .jkn-wf-basics-cell {
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
    margin-bottom: .75rem;
}

.jkn-page .jkn-wf-basics-cell:last-child {
    margin-bottom: 0;
}

.jkn-page .jkn-wf-basics-cell .form-control {
    width: 100%;
}

/* Vital-sign mode: three flat radio-cards. Negative-margin gutters, no
   flex gap (the .jkn-lm-form-grid pattern) for the Windows-7 floor. */
.jkn-page .jkn-wf-mode-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    flex-shrink: 0;
    margin: -.25rem;
}

.jkn-page .jkn-wf-mode-cell {
    width: 100%;
    padding: .25rem;
    box-sizing: border-box;
    display: flex;
    position: relative;
    min-width: 0;
}

/* Visually hidden but real: keyboard arrows, change events, and the
   old-input restore's .prop('checked') all keep working. */
.jkn-page .jkn-wf-mode-input {
    position: absolute;
    top: .75rem;
    left: .75rem;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
}

.jkn-page .jkn-wf-mode-card {
    flex: 1 1 auto;
    margin: 0;
    padding: .65rem .75rem;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    background: #fff;
    cursor: pointer;
    -ms-user-select: none;
    user-select: none;
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.jkn-page .jkn-wf-mode-card:hover {
    background: #f8fafc;
    border-color: #cbd5e1;
}

.jkn-page .jkn-wf-mode-title {
    display: block;
    font-weight: 600;
    font-size: .875rem;
    color: #1e293b;
}

.jkn-page .jkn-wf-mode-title i {
    width: 16px;
    margin-right: .35rem;
    text-align: center;
    color: #94a3b8;
    transition: color .15s ease;
}

.jkn-page .jkn-wf-mode-desc {
    display: block;
    font-size: .72rem;
    font-weight: 400;
    color: #64748b;
    line-height: 1.45;
    margin-top: .2rem;
}

/* Selected: flat violet tint. Declared after :hover so source order wins
   the specificity tie. */
.jkn-page .jkn-wf-mode-input:checked + .jkn-wf-mode-card {
    border-color: #c084fc;
    background: #f5f3ff;
}

.jkn-page .jkn-wf-mode-input:checked + .jkn-wf-mode-card .jkn-wf-mode-title i {
    color: #7c3aed;
}

.jkn-page .jkn-wf-mode-input:checked + .jkn-wf-mode-card .jkn-wf-mode-desc {
    color: #475569;
}

.jkn-page .jkn-wf-mode-input:focus + .jkn-wf-mode-card {
    border-color: #c084fc;
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .15);
}

.jkn-page .jkn-wf-vs-fields {
    flex-shrink: 0;
    margin-top: .45rem;
}

/* Destination kliniks: two-column desktop rowset so a typical facility
   list fits without scrolling the modal. */
.jkn-page .jkn-wf-dest-list {
    display: flex;
    flex-wrap: wrap;
    flex: 1 1 auto;
    min-height: 0;
    align-content: flex-start;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    overflow: visible;
    background: #fff;
}

.jkn-page .jkn-wf-dest-item {
    width: 50%;
    box-sizing: border-box;
    border-bottom: 1px solid #f1f5f9;
}

.jkn-page .jkn-wf-dest-item:nth-child(odd) {
    border-right: 1px solid #f1f5f9;
}

.jkn-page .jkn-wf-dest-row {
    display: flex;
    align-items: center;
    margin: 0;
    padding: .42rem .7rem;
    font-weight: 400;
    cursor: pointer;
    -ms-user-select: none;
    user-select: none;
    transition: background-color .15s ease;
}

.jkn-page .jkn-wf-dest-row:hover {
    background: #f8fafc;
}

.jkn-page .jkn-wf-dest-check {
    flex-shrink: 0;
    margin: 0 .65rem 0 0;
}

.jkn-page .jkn-wf-dest-main {
    flex: 1 1 auto;
    min-width: 0;
}

.jkn-page .jkn-wf-dest-name {
    display: block;
    font-weight: 600;
    font-size: .82rem;
    color: #1e293b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-page .jkn-wf-dest-meta {
    display: block;
    font-size: .68rem;
    font-weight: 400;
    color: #64748b;
    margin-top: 1px;
}

.jkn-page .jkn-wf-dest-row .jkn-chip {
    flex-shrink: 0;
    margin-left: .6rem;
}

/* Checked row: flat violet tint, toggled by JS in syncSkipRows() (no
   :has() on the IE-era floor). Declared after :hover — source order wins
   the specificity tie. */
.jkn-page .jkn-wf-dest-item-on .jkn-wf-dest-row {
    background: #f5f3ff;
}

.jkn-page .jkn-wf-dest-item-on .jkn-wf-dest-meta {
    color: #475569;
}

/* Skip Tanda Vital sub-row: dashed border = bypass, the same language as
   .jkn-wf-node-skip. JS still owns show/hide via .toggle(). */
.jkn-page .jkn-wf-skip-row {
    margin: 0 .7rem .4rem 2.1rem;
    padding: .28rem .5rem;
    border: 1px dashed #cbd5e1;
    border-radius: 8px;
    background: #f8fafc;
}

.jkn-page .jkn-wf-skip-label {
    display: flex;
    align-items: center;
    margin: 0;
    font-size: .78rem;
    font-weight: 400;
    color: #475569;
    cursor: pointer;
    -ms-user-select: none;
    user-select: none;
}

.jkn-page .jkn-wf-skip-check {
    flex-shrink: 0;
    margin: 0 .5rem 0 0;
}

.jkn-page .jkn-wf-dest-empty {
    width: 100%;
    padding: 1.1rem .9rem;
    font-size: .82rem;
    color: #64748b;
    text-align: center;
}

.jkn-page .jkn-wf-dest-hint {
    font-size: .78rem;
    color: #64748b;
    margin: .4rem 0 0;
    flex-shrink: 0;
}

/* Flow preview: sunken tile fills remaining wizard height. Surface-sunken
   #f1f5f9, one step deeper than the vs/skip nodes' #f8fafc. */
.jkn-page .jkn-wf-preview-tile {
    flex: 1 1 auto;
    min-height: 180px;
    display: flex;
    flex-direction: column;
    background: #f1f5f9;
    border-radius: 10px;
    padding: .55rem .7rem .65rem;
    overflow: visible;
}

.jkn-page .jkn-wf-preview-label {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #475569;
    margin-bottom: .35rem;
    flex-shrink: 0;
}

.jkn-page .jkn-wf-preview-tile .jkn-wf-flow {
    flex: 1 1 auto;
    min-height: 0;
    align-items: center;
}

.jkn-page .jkn-wf-preview-tile .jkn-wf-node {
    padding: .4rem .55rem;
}

.jkn-page .jkn-wf-preview-tile .jkn-wf-node-sub {
    display: none;
}

.jkn-page .jkn-wf-preview-tile .jkn-wf-dests .jkn-wf-node:not(.jkn-wf-node-skip) + .jkn-wf-node-skip {
    margin-top: .45rem;
}

.jkn-page .jkn-wf-preview-tile .jkn-wf-flow-bypass {
    padding-bottom: 1.4rem;
}

@media (max-width: 767px) {
    .jkn-page .jkn-wf-dest-item {
        width: 100%;
        border-right: 0;
    }

    .jkn-page .jkn-wf-tab-content > #wfPaneDest.active,
    .jkn-page .jkn-wf-tab-content > #wfPaneReview.active {
        overflow-y: auto;
    }

    .jkn-page .jkn-wf-dest-list {
        overflow-y: auto;
    }
}

@media (max-height: 720px) {
    .jkn-page .jkn-wf-tab-content > #wfPaneDest.active,
    .jkn-page .jkn-wf-tab-content > #wfPaneReview.active {
        overflow-y: auto;
    }

    .jkn-page .jkn-wf-dest-list {
        overflow-y: auto;
        max-height: 240px;
        flex: 0 1 auto;
    }

    .jkn-page .jkn-wf-preview-tile {
        min-height: 140px;
        overflow: auto;
    }
}

    .jkn-page .jkn-wf-preview-tile {
        min-height: 140px;
        overflow: auto;
    }
}

/* ---------- Admin directory (Users + Facilities) ----------
 * Shared control-table vocabulary for JKN Management directory screens.
 * No flex `gap` in IE-critical paths — negative-margin gutters where needed. */

.jkn-page .jkn-dir-card {
    margin-bottom: 0;
}

/* Bento fill: directory cards stretch edge-to-edge and absorb the
 * viewport slot below the page header — no card-body scrollbar on
 * desktop; pagination lives in .jkn-dir-table-footer instead. */
.jkn-page .jkn-bento-main > .row.jkn-bento-row {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    margin-left: 0;
    margin-right: 0;
}

.jkn-page .jkn-bento-main > .row.jkn-bento-row > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
    min-height: 0;
}

.jkn-page .jkn-fill-card.jkn-dir-card {
    height: 100%;
}

.jkn-page .jkn-fill-card.jkn-dir-card > .card-body {
    overflow: hidden;
}

.jkn-page .jkn-dir-card > .card-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

.jkn-page .jkn-dir-card .jkn-command-bar {
    flex-shrink: 0;
    margin-bottom: .55rem;
    padding-bottom: .55rem;
}

.jkn-page .jkn-dir-table-area {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.jkn-page .jkn-dir-table-area .dataTables_wrapper {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.jkn-page .jkn-dir-card .jkn-dir-table-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;
    min-height: 2.75rem;
}

.jkn-page .jkn-dir-card .jkn-dir-table-footer:empty {
    display: none;
    padding: 0;
    border-top: none;
}

.jkn-page .jkn-dir-card .dataTables_wrapper .dataTables_info,
.jkn-page .jkn-dir-card .jkn-dir-table-footer .dataTables_info {
    display: none;
}

.jkn-page .jkn-dir-card .dataTables_wrapper .dataTables_paginate,
.jkn-page .jkn-dir-card .jkn-dir-table-footer .dataTables_paginate {
    float: none;
    margin-left: 0;
    padding-top: 0;
}

.jkn-page .jkn-dir-table th,
.jkn-page .jkn-dir-table td {
    padding-top: .45rem;
    padding-bottom: .45rem;
    vertical-align: middle;
}

.jkn-command-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: .85rem;
    padding-bottom: .85rem;
    border-bottom: 1px solid #eef1f5;
}

.jkn-command-bar-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    margin-right: .75rem;
    margin-bottom: .35rem;
}

.jkn-command-bar-label {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #94a3b8;
    margin-right: .5rem;
    white-space: nowrap;
}

.jkn-role-filter {
    display: inline-flex;
    padding: .2rem;
    background: #f1f5f9;
    border-radius: 10px;
    list-style: none;
    margin: 0;
}

.jkn-role-filter-item {
    margin: 0 .1rem;
}

.jkn-role-filter-item:first-child {
    margin-left: 0;
}

.jkn-role-filter-item:last-child {
    margin-right: 0;
}

.jkn-role-filter-btn {
    display: block;
    padding: .35rem .75rem;
    border: none;
    border-radius: 8px;
    background: transparent;
    font-size: .82rem;
    font-weight: 600;
    color: #475569;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}

.jkn-role-filter-btn:hover {
    color: #1e293b;
}

.jkn-role-filter-btn.active {
    background: #fff;
    color: #3b5bdb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

.jkn-command-bar .jkn-table-search {
    margin-left: auto;
    margin-bottom: .35rem;
}

.jkn-dir-table-meta {
    font-size: .78rem;
    color: #64748b;
    margin-bottom: .45rem;
    flex-shrink: 0;
}

.jkn-page .jkn-dir-table {
    margin-bottom: 0;
}

.jkn-page .jkn-dir-table tbody tr:last-child td {
    border-bottom: none;
}

.jkn-identity-cell {
    display: flex;
    align-items: flex-start;
    min-width: 0;
}

.jkn-identity-cell .jkn-user-avatar,
.jkn-identity-cell .icon-badge {
    flex-shrink: 0;
    margin-right: .7rem;
}

.jkn-identity-body {
    min-width: 0;
    flex: 1 1 auto;
}

.jkn-identity-name {
    display: block;
    font-weight: 700;
    font-size: .875rem;
    color: #1e293b;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-identity-sub {
    display: block;
    font-size: .78rem;
    color: #64748b;
    line-height: 1.35;
    margin-top: .1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-access-summary-title {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: #94a3b8;
    margin-bottom: .25rem;
}

.jkn-access-summary .jkn-chip-list {
    margin-top: .15rem;
}

.jkn-status-cell {
    white-space: nowrap;
}

.jkn-row-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    margin: -.15rem;
}

.jkn-row-actions .btn {
    margin: .15rem;
    white-space: nowrap;
}

.jkn-row-actions .btn-icon-only {
    width: 30px;
    padding-left: 0;
    padding-right: 0;
}

.jkn-row-actions .btn-icon-only .fa {
    margin: 0;
}

.jkn-network-summary {
    min-width: 0;
}

.jkn-network-summary .jkn-ip-chip {
    margin-bottom: .2rem;
}

.jkn-feed-state {
    display: block;
    font-size: .72rem;
    color: #64748b;
    margin-top: .25rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.jkn-feed-state i {
    margin-right: .25rem;
    color: #94a3b8;
}

.jkn-page-header-stats.jkn-header-stats-compact .jkn-header-stat {
    margin-left: 1.25rem;
}

.jkn-page-header-stats.jkn-header-stats-compact .jkn-stat-value {
    font-size: 1.25rem;
}

/* Directory modals */
.jkn-page .jkn-dir-dialog {
    max-width: 640px;
}

.jkn-page .jkn-dir-dialog-lg {
    max-width: 920px;
}

.jkn-page .jkn-dir-dialog .modal-header {
    padding: .75rem 1.15rem;
}

.jkn-page .jkn-dir-dialog .modal-footer {
    padding: .7rem 1.15rem;
}

.jkn-page .jkn-dir-dialog .modal-body {
    padding: 1rem 1.15rem;
}

.jkn-dir-modal-intro {
    font-size: .82rem;
    color: #64748b;
    margin-bottom: .85rem;
}

.jkn-access-mode-grid {
    display: flex;
    flex-wrap: wrap;
    margin: -.25rem -.25rem .65rem;
}

.jkn-access-mode-cell {
    width: 50%;
    padding: .25rem;
    box-sizing: border-box;
    position: relative;
    display: flex;
    min-width: 0;
}

.jkn-access-mode-input {
    position: absolute;
    top: .75rem;
    left: .75rem;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
}

.jkn-access-mode-card {
    flex: 1 1 auto;
    margin: 0;
    padding: .65rem .75rem;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    background: #fff;
    cursor: pointer;
    -ms-user-select: none;
    user-select: none;
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.jkn-access-mode-card:hover {
    background: #f8fafc;
    border-color: #cbd5e1;
}

.jkn-access-mode-title {
    display: block;
    font-weight: 600;
    font-size: .875rem;
    color: #1e293b;
}

.jkn-access-mode-desc {
    display: block;
    font-size: .72rem;
    color: #64748b;
    line-height: 1.4;
    margin-top: .15rem;
}

.jkn-access-mode-input:checked + .jkn-access-mode-card {
    border-color: #93c5fd;
    background: #eef2ff;
}

.jkn-access-mode-input:checked + .jkn-access-mode-card .jkn-access-mode-title {
    color: #3b5bdb;
}

.jkn-access-mode-input:focus + .jkn-access-mode-card {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

.jkn-facility-pick-panel {
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    padding: .75rem;
    background: #f8fafc;
}

.jkn-dir-modal-split {
    display: flex;
    flex-wrap: wrap;
    margin: 0 -.45rem;
}

.jkn-dir-modal-col {
    width: 50%;
    padding: 0 .45rem;
    box-sizing: border-box;
    min-width: 0;
}

.jkn-facility-toolbar.jkn-command-bar {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

.jkn-facility-toolbar .form-row {
    width: 100%;
    margin: 0;
}

@media (max-width: 991px) {
    .jkn-dir-modal-col,
    .jkn-access-mode-cell {
        width: 100%;
    }

    .jkn-command-bar .jkn-table-search {
        width: 100%;
        margin-left: 0;
    }

    .jkn-command-bar .jkn-table-search input {
        width: 100%;
    }

    .jkn-page .jkn-dir-col-hide-sm {
        display: none;
    }
}

@media (max-width: 767px) {
    .jkn-row-actions {
        justify-content: flex-start;
    }

    .jkn-page-header-stats.jkn-header-stats-compact {
        width: 100%;
        margin-left: 0;
        margin-top: .65rem;
    }
}

/* ---------- Add/Edit Facility wizard ----------
 * Same 3-short-steps-instead-of-one-long-form pattern as the Add/Edit
 * Location wizard (see its comment further up this file): Identity,
 * Location (lat/lng), then Network Access — each short enough that the
 * modal body never needs .jkn-modal-scroll.
 *
 * Namespaced .jkn-fac-wizard-* rather than reusing .jkn-wizard-* (Third
 * Party QMS, amber) or .jkn-loc-wizard-* (counters, violet) — same reason
 * as the counter wizard's own comment: equal-specificity class reuse across
 * differently-colored wizards silently breaks step-hiding.
 */
.jkn-fac-wizard-dialog {
    max-width: 620px;
}

.jkn-page .jkn-fac-wizard-nav {
    display: flex;
    align-items: flex-start;
    padding: 1.1rem 1.15rem .3rem;
}

.jkn-page .jkn-fac-wizard-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 auto;
}

.jkn-page .jkn-fac-wizard-nav-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: #eef1f5;
    color: #94a3b8;
    font-size: .78rem;
    font-weight: 700;
    flex-shrink: 0;
    transition: background-color .15s ease, color .15s ease;
}

.jkn-page .jkn-fac-wizard-nav-label {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: #94a3b8;
    margin-top: .35rem;
    white-space: nowrap;
    transition: color .15s ease;
}

.jkn-page .jkn-fac-wizard-nav-item.active .jkn-fac-wizard-nav-circle,
.jkn-page .jkn-fac-wizard-nav-item.done .jkn-fac-wizard-nav-circle {
    /* Verbatim from .icon-badge-green above, not a new gradient value. */
    background: linear-gradient(135deg, #6ee7b7 0%, #059669 100%);
    color: #fff;
    box-shadow: 0 6px 14px -5px rgba(5, 150, 105, .5);
}

.jkn-page .jkn-fac-wizard-nav-item.active .jkn-fac-wizard-nav-label {
    color: #3b5bdb;
}

.jkn-page .jkn-fac-wizard-nav-item.done .jkn-fac-wizard-nav-label {
    color: #475569;
}

.jkn-page .jkn-fac-wizard-nav-line {
    flex: 1 1 auto;
    height: 2px;
    background: #e2e8f0;
    margin: 13px .5rem 0;
    transition: background-color .15s ease;
}

.jkn-page .jkn-fac-wizard-nav-line.done {
    background: #059669;
}

.jkn-fac-wizard-body {
    padding-top: .6rem;
}

.jkn-fac-wizard-step {
    display: none;
}

.jkn-fac-wizard-step.active {
    display: block;
    animation: jknFacWizardStepIn .15s ease;
}

@keyframes jknFacWizardStepIn {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ---------- Email branding (bento editor + live preview) ---------- */

.jkn-page .jkn-email-bento-card > .card-header {
    flex-shrink: 0;
}

.jkn-email-bento-header-reset {
    margin-left: auto;
    flex-shrink: 0;
}

.jkn-email-bento-reset {
    margin: 0;
}

.jkn-fill-card > .jkn-email-bento-save-form {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.jkn-email-bento-save-form .jkn-email-bento-body {
    flex: 1 1 auto;
    min-height: 0;
}

.jkn-email-bento-header-note {
    font-size: .78rem;
    color: #64748b;
    font-weight: 400;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 45%;
    margin-left: .75rem;
}

.jkn-page .jkn-email-bento-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    padding: 1rem 1.15rem;
}

.jkn-email-bento-grid {
    display: flex;
    flex-wrap: wrap;
    height: 100%;
    min-height: 0;
    margin: 0 -.45rem;
}

.jkn-email-bento-editor {
    width: 58%;
    padding: 0 .45rem;
    box-sizing: border-box;
    min-height: 0;
    overflow-y: auto;
}

.jkn-email-bento-preview {
    width: 42%;
    padding: 0 .45rem;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.jkn-email-bento-tiles {
    display: flex;
    flex-wrap: wrap;
    margin: -.35rem;
}

.jkn-email-bento-tile {
    width: 100%;
    padding: .35rem;
    box-sizing: border-box;
}

.jkn-email-bento-tile-half {
    width: 50%;
}

.jkn-email-bento-tile-inner {
    background: #f8fafc;
    border: 1px solid #eef1f5;
    border-radius: 10px;
    padding: .75rem .85rem;
    height: 100%;
    box-sizing: border-box;
}

.jkn-email-bento-tile-head {
    display: flex;
    align-items: center;
    margin-bottom: .65rem;
}

.jkn-email-bento-tile-head .icon-badge {
    margin-right: .5rem;
    flex-shrink: 0;
}

.jkn-email-bento-tile-title {
    font-size: .82rem;
    font-weight: 700;
    color: #1e293b;
}

.jkn-email-bento-fields-row {
    display: flex;
    flex-wrap: wrap;
    margin: 0 -.35rem;
}

.jkn-email-bento-field {
    width: 33.333%;
    padding: 0 .35rem;
    box-sizing: border-box;
    min-width: 0;
}

.jkn-email-bento-help-text {
    font-size: .78rem;
    color: #64748b;
    line-height: 1.45;
    margin: 0 0 .65rem 0;
}


.jkn-email-bento-preview-head {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin-bottom: .65rem;
}

.jkn-email-bento-preview-head .icon-badge {
    margin-right: .5rem;
}

.jkn-email-bento-preview-title {
    font-size: .875rem;
    font-weight: 700;
    color: #1e293b;
}

.jkn-email-bento-preview-badge {
    margin-left: auto;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: #64748b;
    background: #f1f5f9;
    border-radius: 999px;
    padding: .2rem .55rem;
}

.jkn-page .jkn-email-bento-preview .jkn-email-preview-frame {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    margin-bottom: .45rem;
}

.jkn-email-preview-note {
    font-size: .72rem;
    color: #94a3b8;
    margin: 0;
    flex-shrink: 0;
    text-align: center;
}

.jkn-page .jkn-email-bento-footer {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}

.jkn-email-preview-frame {
    background: #f1f5f9;
    border: 1px solid #eef1f5;
    border-radius: 10px;
    padding: .75rem;
}

.jkn-email-preview-shell {
    background: #ffffff;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    overflow: hidden;
    font-size: .72rem;
    line-height: 1.45;
}

.jkn-email-preview-header {
    display: flex;
    align-items: center;
    background: #3b5bdb;
    padding: .65rem .75rem;
}

.jkn-email-preview-logo {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 9px;
    margin-right: .65rem;
}

.jkn-email-preview-header-text {
    min-width: 0;
    flex: 1 1 auto;
}

.jkn-email-preview-header-title {
    font-weight: 700;
    font-size: .82rem;
    color: #ffffff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-email-preview-header-sub {
    font-size: .68rem;
    color: #dbeafe;
    margin-top: .1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jkn-email-preview-body {
    padding: .75rem;
    color: #334155;
}

.jkn-email-preview-subject {
    font-size: .68rem;
    font-weight: 700;
    color: #64748b;
    margin-bottom: .55rem;
    padding-bottom: .55rem;
    border-bottom: 1px solid #eef1f5;
    word-break: break-word;
}

.jkn-email-preview-title {
    font-size: .85rem;
    font-weight: 700;
    color: #1e293b;
    margin-bottom: .45rem;
}

.jkn-email-preview-copy {
    margin: 0 0 .45rem 0;
    font-size: .72rem;
}

.jkn-email-preview-copy:last-child {
    margin-bottom: 0;
}

.jkn-email-preview-muted {
    color: #64748b;
}

.jkn-email-preview-cta {
    display: inline-block;
    color: #3b5bdb;
    font-weight: 600;
    text-decoration: underline;
}

.jkn-email-preview-footer {
    background: #f8fafc;
    border-top: 1px solid #eef1f5;
    padding: .65rem .75rem;
    text-align: center;
}

.jkn-email-preview-footer-strong {
    font-weight: 600;
    font-size: .72rem;
    color: #1e293b;
    margin-bottom: .15rem;
    word-break: break-word;
}

.jkn-email-preview-footer-line {
    font-size: .68rem;
    color: #64748b;
    margin-bottom: .35rem;
    word-break: break-word;
}

.jkn-email-preview-footer-contact {
    font-size: .68rem;
    color: #3b5bdb;
    font-weight: 600;
    word-break: break-all;
}

@media (max-width: 991px) {
    .jkn-email-bento-editor,
    .jkn-email-bento-preview {
        width: 100%;
    }

    .jkn-email-bento-preview {
        margin-top: .75rem;
    }

    .jkn-email-bento-tile-half {
        width: 100%;
    }

    .jkn-email-bento-field {
        width: 100%;
        margin-bottom: .5rem;
    }

    .jkn-email-bento-header-note {
        display: none;
    }

    .jkn-email-bento-header-reset .btn {
        font-size: .72rem;
        padding: .2rem .45rem;
    }
}

@media (max-width: 767px) {
    .jkn-page .jkn-email-bento-body {
        overflow-y: auto;
    }
}

/* ---------- Dashboard (/home) ----------
 * Stat tiles that double as links reuse .jkn-stat-tile verbatim — only
 * link-specific resets (no underline, no color change) are added here, and
 * only a background hover (interactive control), never the Static Card
 * Rule's forbidden lift/shadow-grow. */
.jkn-page a.jkn-stat-tile-link {
    color: inherit;
    text-decoration: none;
}

.jkn-page a.jkn-stat-tile-link:hover {
    background: #f8fafc;
}

.jkn-stat-go {
    margin-left: auto;
    color: #94a3b8;
    font-size: .8rem;
}

.jkn-home-service-row {
    display: flex;
    align-items: center;
    padding: .55rem 0;
    border-bottom: 1px solid #f1f5f9;
}

.jkn-home-service-row:last-child {
    border-bottom: 0;
}

.jkn-home-service-row .jkn-status-chip {
    margin-left: auto;
}

.jkn-home-log {
    background: #f1f5f9;
    border-radius: 10px;
    padding: .85rem 1rem;
    font-size: .82rem;
    margin: 0;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ---------- Visitor reports (/reports) ----------
 * Report navigation sits above the annual page's bounded .jkn-page, so it
 * owns the same segmented-control treatment without relying on ancestry.
 * Report-only layout uses margins rather than flex gap for old Edge/IE. */
.jkn-report-tabs {
    border-bottom: 0;
    background: #f1f5f9;
    display: inline-flex;
    padding: .3rem;
    border-radius: 10px;
    margin-bottom: 1rem;
}

.jkn-report-tabs .nav-item {
    margin-bottom: 0;
    margin-right: .25rem;
}

.jkn-report-tabs .nav-item:last-child {
    margin-right: 0;
}

.jkn-report-tabs .nav-link {
    border: 0;
    border-radius: 8px;
    padding: .5rem 1rem;
    color: #475569;
    font-size: .875rem;
    font-weight: 600;
    transition: color .15s ease, background-color .15s ease, box-shadow .15s ease;
}

.jkn-report-tabs .nav-link:hover {
    color: #1e293b;
}

.jkn-report-tabs .nav-link.active {
    background: #fff;
    color: #3b5bdb;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

.jkn-page.jkn-report-page {
    height: calc(100vh - 12rem);
}

.jkn-report-page .jkn-page-header {
    margin-bottom: 1rem;
}

.jkn-report-year-form {
    display: flex;
    align-items: center;
    margin-left: auto;
}

.jkn-report-year-form label,
.jkn-report-facility-filter label {
    margin: 0 .55rem 0 0;
    color: #64748b;
    font-size: .78rem;
    font-weight: 600;
    white-space: nowrap;
}

.jkn-report-year-form select {
    width: 92px;
    margin-right: .5rem;
}

.jkn-report-year-form select:focus,
.jkn-report-facility-filter select:focus {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

.jkn-report-main {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 1px 2px .5rem;
}

.jkn-report-stats {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    margin-bottom: .5rem;
}

.jkn-report-stat-copy {
    min-width: 0;
}

.jkn-report-stat-text {
    max-width: 230px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 1.05rem;
}

.jkn-report-chart-card,
.jkn-report-table-card {
    flex-shrink: 0;
}

.jkn-report-facility-filter {
    display: flex;
    align-items: center;
    max-width: 390px;
}

.jkn-report-facility-filter select {
    width: 250px;
}

.jkn-report-chart-wrap {
    position: relative;
    height: 300px;
}

.jkn-report-empty {
    display: flex;
    align-items: center;
    min-height: 180px;
    padding: 1.25rem;
    border-radius: 11px;
    background: #f8fafc;
    color: #1e293b;
}

.jkn-report-empty .icon-badge {
    margin-right: 1rem;
}

.jkn-report-empty p {
    margin: .2rem 0 0;
    color: #64748b;
}

.jkn-report-table-card .card-body {
    padding-top: .9rem;
}

.jkn-report-table-meta {
    color: #64748b;
    font-size: .82rem;
    padding: .4rem 0;
}

.jkn-page .jkn-report-table-area {
    display: block;
    overflow-x: auto;
    overflow-y: visible;
    width: 100%;
}

.jkn-page .jkn-report-table-area .dataTables_wrapper {
    display: block;
    min-width: 1050px;
    overflow: visible;
}

.jkn-page .jkn-report-table {
    min-width: 1050px;
    margin-bottom: 0;
    text-align: right;
}

.jkn-page .jkn-report-table thead th,
.jkn-page .jkn-report-table tbody td {
    text-align: right;
    white-space: nowrap;
}

.jkn-page .jkn-report-table thead th:first-child,
.jkn-page .jkn-report-table tbody th {
    min-width: 220px;
    text-align: left;
}

.jkn-page .jkn-report-table tbody th {
    padding: .8rem .75rem;
    border-top: 1px solid #f1f5f9;
    color: #334155;
    font-weight: 600;
}

.jkn-page .jkn-report-table .jkn-report-total {
    color: #1e293b;
    background: #f8fafc;
    font-weight: 700;
}

@media (max-width: 767px) {
    .jkn-page.jkn-report-page {
        height: calc(100vh - 11.5rem);
    }

    .jkn-report-page .jkn-page-header {
        align-items: flex-start;
    }

    .jkn-report-year-form {
        width: 100%;
        margin: .85rem 0 0;
    }

    .jkn-report-year-form select {
        flex: 1 1 auto;
        width: auto;
    }

    .jkn-report-chart-card .card-header {
        flex-wrap: wrap;
    }

    .jkn-report-facility-filter {
        width: 100%;
        max-width: none;
        margin: .75rem 0 0 !important;
    }

    .jkn-report-facility-filter select {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }

    .jkn-report-chart-wrap {
        height: 250px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .jkn-report-tabs .nav-link {
        transition: none;
    }
}

/* ---------- Facility directory refresh ----------
 * A compact live-filter cluster replaces the loose full-width toolbar while
 * retaining a normal GET form as the no-JS fallback. */
.jkn-page .jkn-facility-dir-card > .card-body {
    border-radius: 14px;
}

.jkn-page .jkn-facility-toolbar.jkn-command-bar {
    flex-wrap: nowrap;
    margin: 0 0 .65rem;
    padding: .65rem .7rem;
    border: 1px solid #eef1f5;
    border-radius: 11px;
    background: #f8fafc;
}

.jkn-facility-filter-cluster {
    display: flex;
    align-items: center;
    min-width: 0;
}

.jkn-page .jkn-facility-filter-cluster .jkn-table-search {
    margin: 0 .65rem 0 0;
}

.jkn-page .jkn-facility-filter-cluster .jkn-table-search input {
    width: 290px;
    background: #fff;
}

.jkn-facility-type-filter {
    display: flex;
    align-items: center;
    margin-right: .55rem;
}

.jkn-facility-type-filter select {
    width: 190px;
    background: #fff;
}

.jkn-facility-toolbar .jkn-command-bar-label {
    margin-bottom: 0;
}

.jkn-facility-toolbar.jkn-live-ready .js-facility-apply {
    display: none;
}

.jkn-facility-toolbar .jkn-clear-link {
    margin-left: .1rem;
}

.jkn-facility-toolbar-utility {
    margin-left: auto;
    padding-left: .75rem;
    flex-shrink: 0;
}

.jkn-facility-mobile-summary {
    display: none;
    margin-top: .35rem;
}

.jkn-mobile-meta-item {
    display: inline-block;
    margin: .2rem .55rem 0 0;
    color: #64748b;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
}

.jkn-mobile-meta-item i {
    margin-right: .2rem;
    color: #94a3b8;
}

.jkn-mobile-meta-warn,
.jkn-mobile-meta-warn i {
    color: #c2410c;
}

.jkn-page .jkn-dir-load-error {
    min-height: 6rem;
    border: 1px solid #fecaca;
    border-radius: 10px;
    background: #fef2f2;
}

.jkn-page .jkn-dir-load-error .dataTables_wrapper {
    opacity: .45;
}

.jkn-page .jkn-dir-load-error + .jkn-dir-table-footer {
    display: none;
}

@media (max-width: 991px) {
    .jkn-page .jkn-facility-toolbar.jkn-command-bar {
        flex-wrap: wrap;
    }

    .jkn-facility-filter-cluster {
        flex: 1 1 auto;
    }

    .jkn-page .jkn-facility-filter-cluster .jkn-table-search {
        width: auto;
        margin-right: .55rem;
    }

    .jkn-page .jkn-facility-filter-cluster .jkn-table-search input {
        width: 230px;
    }

    .jkn-facility-mobile-summary {
        display: block;
    }
}

@media (max-width: 767px) {
    .jkn-facility-page .jkn-page-header-stats.jkn-header-stats-compact {
        display: flex;
        width: 100%;
        margin: .75rem 0 0;
    }

    .jkn-facility-page .jkn-page-header-stats.jkn-header-stats-compact .jkn-header-stat {
        width: 50%;
        margin: 0 0 .55rem;
        padding-right: .75rem;
        box-sizing: border-box;
        text-align: left;
    }

    .jkn-facility-page .jkn-page-header-action {
        margin: .15rem 0 0;
    }

    .jkn-page .jkn-facility-toolbar.jkn-command-bar {
        display: block;
        padding: .7rem;
    }

    .jkn-facility-filter-cluster {
        display: block;
        width: 100%;
    }

    .jkn-page .jkn-facility-filter-cluster .jkn-table-search {
        width: 100%;
        margin: 0 0 .55rem;
    }

    .jkn-page .jkn-facility-filter-cluster .jkn-table-search input {
        width: 100%;
    }

    .jkn-facility-type-filter {
        margin: 0;
    }

    .jkn-facility-type-filter select {
        flex: 1 1 auto;
        width: auto;
    }

    .jkn-facility-toolbar .js-facility-apply {
        margin-top: .55rem;
    }

    .jkn-facility-toolbar .jkn-clear-link {
        margin-top: .55rem;
    }

    .jkn-facility-toolbar-utility {
        margin: .65rem 0 0;
        padding: .65rem 0 0;
        border-top: 1px solid #e2e8f0;
    }

    .jkn-facility-toolbar-utility .btn {
        width: 100%;
    }

    .jkn-page .jkn-dir-col-hide-xs {
        display: none !important;
    }

    #facilitiesTable th:nth-child(2),
    #facilitiesTable td:nth-child(2) {
        width: 68% !important;
    }

    #facilitiesTable th:nth-child(5),
    #facilitiesTable td:nth-child(5) {
        width: 32% !important;
    }

    .jkn-facility-cell .icon-badge {
        width: 26px;
        height: 26px;
        border-radius: 8px;
        font-size: .72rem;
    }

    .jkn-page .jkn-facility-table td {
        padding-left: .45rem;
        padding-right: .45rem;
    }

    .jkn-page .jkn-facility-table .jkn-row-actions .btn {
        width: 100%;
        text-align: center;
    }
}

/* ---------- Locations directory (/settings/qms) ----------
 * Scoped to the Locations DataTable card only — Workflow + Rows + Search
 * share one command bar; page length is remembered per facility. */
.jkn-page .jkn-locations-dir-card > .card-body {
    border-radius: 0;
}

.jkn-page .jkn-locations-toolbar.jkn-command-bar {
    flex-wrap: nowrap;
    margin: 0 0 .55rem;
    padding: .55rem .65rem;
    border: 1px solid #eef1f5;
    border-radius: 11px;
    background: #f8fafc;
}

.jkn-locations-filter-cluster {
    display: flex;
    align-items: center;
    min-width: 0;
    flex: 1 1 auto;
}

.jkn-locations-workflow-filter,
.jkn-locations-page-size {
    display: flex;
    align-items: center;
    margin-right: .65rem;
}

.jkn-locations-workflow-filter select {
    width: 190px;
    background: #fff;
}

.jkn-locations-page-size select {
    width: 72px;
    background: #fff;
}

.jkn-page .jkn-locations-toolbar .jkn-command-bar-label {
    margin-bottom: 0;
}

.jkn-page .jkn-locations-toolbar .jkn-table-search {
    margin: 0 0 0 auto;
}

.jkn-page .jkn-locations-toolbar .jkn-table-search input {
    width: 220px;
    background: #fff;
}

.jkn-page .jkn-locations-toolbar .form-control:focus {
    border-color: #93c5fd;
    box-shadow: 0 0 0 3px rgba(59, 91, 219, .12);
}

@media (max-width: 991px) {
    .jkn-page .jkn-locations-toolbar.jkn-command-bar {
        flex-wrap: wrap;
    }

    .jkn-locations-filter-cluster {
        width: 100%;
        margin-bottom: .45rem;
    }

    .jkn-page .jkn-locations-toolbar .jkn-table-search {
        width: 100%;
        margin-left: 0;
    }

    .jkn-page .jkn-locations-toolbar .jkn-table-search input {
        width: 100%;
    }
}

@media (max-width: 767px) {
    .jkn-locations-filter-cluster {
        display: block;
    }

    .jkn-locations-workflow-filter,
    .jkn-locations-page-size {
        width: 100%;
        margin: 0 0 .45rem;
    }

    .jkn-locations-workflow-filter select,
    .jkn-locations-page-size select {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }
}
