/* ==========================================================================
   Tech4TIME — pages/service-detail.css
   Shared by the four service detail pages under /pages/services/. Ports the
   NextJS dashboards (SecurityDashboard and its siblings): the layer tabs, the
   node map around a central hub, and the solution card grid.

   The NextJS originals separate their two layers by colour — green for
   proactive, red for reactive. This palette has no hue, and colour alone would
   fail WCAG 1.4.1 in any case, so the layers are told apart by icon, title and
   position instead.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Core capability cards
   -------------------------------------------------------------------------- */

.core-solutions__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
}

.core-card {
  padding: var(--space-xl);
  background-color: var(--bg-elevated);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-lg);
  transition:
    transform var(--duration) var(--ease-out),
    border-color var(--duration) var(--ease-out),
    box-shadow var(--duration) var(--ease-out);
}

.core-card:hover {
  transform: translateY(-4px);
  border-color: var(--silver-accent-mid);
  box-shadow: var(--shadow);
}

.core-card__icon {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  margin-block-end: var(--space-md);
  font-size: 1.5rem;
  color: var(--on-accent);
  background-image: var(--silver-gradient-fill);
  border-radius: var(--radius);
}

.core-card__title {
  margin-block-end: var(--space-xs);
  font-size: var(--text-lg);
}

.core-card__text {
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

.core-solutions__note {
  margin-block-start: var(--space-lg);
  font-size: var(--text-sm);
  text-align: center;
  color: var(--text-secondary);
}

.core-solutions__note a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  white-space: nowrap;
  font-weight: 600;
  color: var(--accent-text);
}

/* This has to be said again here. `a:hover` in base.css and this rule are both
   one class-level and one type, so they tie on specificity and the later file
   wins — setting the colour above silently took the hover away with it. The
   same override elsewhere (.job__body a, .legal__body a) restates the hover;
   this one had been missed, on all six service pages. */
.core-solutions__note a:hover {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Nudge the arrow along, as the service cards on the home page do. */
.core-solutions__note a .icon {
  transition: transform var(--duration) var(--ease-out);
}

.core-solutions__note a:hover .icon {
  transform: translateX(0.25rem);
}

/* --------------------------------------------------------------------------
   2. Layer tabs
   The base .tabs component is a row of pills. The dashboards use something
   closer to a sidebar: an icon, a name and a line explaining the layer. This
   modifier supplies that without disturbing the pill variant.
   -------------------------------------------------------------------------- */

.tabs--cards .tabs__list {
  display: grid;
  gap: var(--space-sm);
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}

.tabs--cards .tabs__tab {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  min-height: 0;
  padding: var(--space-md);
  font-size: var(--text-base);
  font-weight: 400;
  text-align: start;
  text-decoration: none;
  background-color: var(--bg-elevated);
  border-radius: var(--radius-lg);
}

.tabs--cards .tabs__tab[aria-selected="true"] {
  color: var(--text-primary);
  background-color: var(--bg-elevated);
  background-image: none;
  border-color: var(--silver-accent-mid);
  box-shadow: var(--shadow-sm);
}

/* The selected tab needs a marker that is not colour. A solid silver bar down
   its leading edge does the job, and the ARIA state carries it for anyone not
   looking at the screen. */
.tabs--cards .tabs__tab[aria-selected="true"]::before {
  content: "";
  position: absolute;
  inset-block: var(--space-sm);
  inset-inline-start: 0;
  width: 4px;
  background-image: var(--silver-gradient-fill);
  border-radius: var(--radius-full);
}

.tabs--cards .tabs__tab {
  position: relative;
}

.tabs--cards .tabs__tab-icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.125rem;
  color: var(--accent-text);
  background-color: var(--bg-surface);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius);
  transition:
    color var(--duration) var(--ease-out),
    background-color var(--duration) var(--ease-out),
    border-color var(--duration) var(--ease-out);
}

.tabs--cards .tabs__tab[aria-selected="true"] .tabs__tab-icon {
  color: var(--on-accent);
  background-image: var(--silver-gradient-fill);
  border-color: transparent;
}

.tabs--cards .tabs__tab-body {
  min-width: 0;
}

.tabs--cards .tabs__tab-name {
  display: block;
  font-weight: 650;
  color: var(--text-primary);
}

.tabs--cards .tabs__tab-text {
  display: block;
  margin-block-start: var(--space-3xs);
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
}

/* Without JavaScript both panels stay on the page, one after the other, and
   the tabs above are ordinary jump links. A rule between them keeps that
   reading as two sections rather than one run-on list.

   The :not([hidden]) on the FIRST of the pair is what matters: once the tabs
   are live only one panel is on screen, and without this the survivor still
   drew a rule and four rems of padding above itself, leaving an empty gap
   under the tabs — and only ever above the second panel, so the two layers did
   not even match each other. */
.layer:not([hidden]) + .layer {
  margin-block-start: var(--space-2xl);
  padding-block-start: var(--space-2xl);
  border-block-start: var(--border-width) solid var(--border-subtle);
}

/* --------------------------------------------------------------------------
   3. Layer header
   -------------------------------------------------------------------------- */

.layer__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  margin-block-end: var(--space-xl);
  padding: var(--space-lg);
  background-color: var(--bg-elevated);
  border: var(--border-width) solid var(--border-subtle);
  border-inline-start: 4px solid var(--silver-accent-mid);
  border-radius: var(--radius-lg);
}

.layer__title {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-block-end: var(--space-2xs);
  font-size: var(--text-xl);
}

.layer__icon {
  color: var(--accent-text);
}

.layer__text {
  max-width: 52rem;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

.layer__count {
  flex-shrink: 0;
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--text-sm);
  font-weight: 650;
  white-space: nowrap;
  color: var(--text-primary);
  background-color: var(--bg-surface);
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-full);
}

/* --------------------------------------------------------------------------
   4. Node map
   The dashboards scatter each solution around a central hub and swap a detail
   card as you move across them. Here the nodes sit on an even ring, driven by
   two custom properties: --n, how many nodes, and --i, which one this is. That
   keeps the whole thing to plain classes with no inline styles — the CSP on
   this site is style-src 'self', so per-node inline positioning could not run
   at all.

   Panels vary from three nodes to twenty-one, so the ring comes in three sizes
   rather than crowding twenty-one nodes onto a circle built for twelve.

   Every node repeats a card in the grid below, so the ring is a shortcut, not
   the only route to the content: it goes entirely under 52em, where a ring of
   nodes would be illegible.
   -------------------------------------------------------------------------- */

.layer__viz {
  display: none;
}

@media (min-width: 52em) {
  .layer__viz {
    display: grid;
    gap: var(--space-xl);
    align-items: center;
    justify-items: center;
    margin-block-end: var(--space-2xl);
  }

  .soc-map {
    /* Defaults suit the eight-to-fourteen node case. */
    --n: 12;
    --size: 26rem;
    --radius: 10.75rem;
    --node: 3.25rem;

    position: relative;
    width: var(--size);
    height: var(--size);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .soc-map--sm {
    --size: 21rem;
    --radius: 8rem;
  }

  .soc-map--lg {
    --size: 32rem;
    --radius: 13.5rem;
    --node: 2.75rem;
  }

  .soc-map--n2 { --n: 2; }
  .soc-map--n3 { --n: 3; }
  .soc-map--n4 { --n: 4; }
  .soc-map--n5 { --n: 5; }
  .soc-map--n6 { --n: 6; }
  .soc-map--n7 { --n: 7; }
  .soc-map--n8 { --n: 8; }
  .soc-map--n9 { --n: 9; }
  .soc-map--n10 { --n: 10; }
  .soc-map--n11 { --n: 11; }
  .soc-map--n12 { --n: 12; }
  .soc-map--n13 { --n: 13; }
  .soc-map--n14 { --n: 14; }
  .soc-map--n15 { --n: 15; }
  .soc-map--n16 { --n: 16; }
  .soc-map--n17 { --n: 17; }
  .soc-map--n18 { --n: 18; }
  .soc-map--n19 { --n: 19; }
  .soc-map--n20 { --n: 20; }
  .soc-map--n21 { --n: 21; }
  .soc-map--n22 { --n: 22; }
  .soc-map--n23 { --n: 23; }
  .soc-map--n24 { --n: 24; }

  /* Spokes: one hairline per node, masked to a ring so they neither cross the
     hub nor run past the nodes. The gradient starts at twelve o'clock, which is
     exactly where the --i: 0 node sits, so spokes and nodes stay in step at any
     count. */
  .soc-map::before {
    content: "";
    position: absolute;
    inset: 0;
    /* Decoration only. Both pseudo-elements paint above the nodes, which are
       ordinary in-flow content, and a pseudo-element hit-tests over its whole
       box whatever it paints — the mask below hides most of this one but hides
       none of it from the pointer. The ring in ::after covers the inner half
       of every node, so a click aimed at a node's centre was landing on the
       <ul>. tools/check_hover.py caught it by moving a real pointer. */
    pointer-events: none;
    border-radius: 50%;
    background-image: repeating-conic-gradient(
      from -0.2deg,
      var(--border-strong) 0deg 0.4deg,
      transparent 0.4deg calc(360deg / var(--n))
    );
    -webkit-mask-image: radial-gradient(closest-side, transparent 0 27%, #000 29% 80%, transparent 82%);
    mask-image: radial-gradient(closest-side, transparent 0 27%, #000 29% 80%, transparent 82%);
  }

  /* The ring the nodes sit on. */
  .soc-map::after {
    content: "";
    position: absolute;
    inset: calc(var(--size) / 2 - var(--radius));
    pointer-events: none;             /* see ::before */
    border: var(--border-width) dashed var(--border-subtle);
    border-radius: 50%;
  }

  /* Flex, not grid: two auto grid rows stretch to fill the circle and centre
     their contents separately, which pushed the icon into the top half and the
     label into the bottom. Flex with justify-content centres them as one unit. */
  .soc-map__hub {
    position: absolute;
    top: 50%;
    left: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3xs);
    width: 7rem;
    height: 7rem;
    margin: -3.5rem;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--on-accent);
    background-image: var(--silver-gradient-fill);
    border-radius: 50%;
    box-shadow: var(--shadow);
  }

  .soc-map__hub-label {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--tracking-wider);
  }

  .soc-map__slot {
    /* Fallback so a slot past the last nth-child rule stacks at the top rather
       than breaking the transform outright. */
    --i: 0;

    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--node);
    height: var(--node);
    margin: calc(var(--node) / -2);
    /* Out to the ring, then counter-rotate so the icon stays upright. */
    transform:
      rotate(calc(var(--i) / var(--n) * 360deg))
      translateY(calc(var(--radius) * -1))
      rotate(calc(var(--i) / var(--n) * -360deg));
  }

  /* Child 1 is the hub, so the nodes start at child 2. */
  .soc-map__slot:nth-child(2 ) { --i: 0 ; }
  .soc-map__slot:nth-child(3 ) { --i: 1 ; }
  .soc-map__slot:nth-child(4 ) { --i: 2 ; }
  .soc-map__slot:nth-child(5 ) { --i: 3 ; }
  .soc-map__slot:nth-child(6 ) { --i: 4 ; }
  .soc-map__slot:nth-child(7 ) { --i: 5 ; }
  .soc-map__slot:nth-child(8 ) { --i: 6 ; }
  .soc-map__slot:nth-child(9 ) { --i: 7 ; }
  .soc-map__slot:nth-child(10) { --i: 8 ; }
  .soc-map__slot:nth-child(11) { --i: 9 ; }
  .soc-map__slot:nth-child(12) { --i: 10; }
  .soc-map__slot:nth-child(13) { --i: 11; }
  .soc-map__slot:nth-child(14) { --i: 12; }
  .soc-map__slot:nth-child(15) { --i: 13; }
  .soc-map__slot:nth-child(16) { --i: 14; }
  .soc-map__slot:nth-child(17) { --i: 15; }
  .soc-map__slot:nth-child(18) { --i: 16; }
  .soc-map__slot:nth-child(19) { --i: 17; }
  .soc-map__slot:nth-child(20) { --i: 18; }
  .soc-map__slot:nth-child(21) { --i: 19; }
  .soc-map__slot:nth-child(22) { --i: 20; }
  .soc-map__slot:nth-child(23) { --i: 21; }
  .soc-map__slot:nth-child(24) { --i: 22; }
  .soc-map__slot:nth-child(25) { --i: 23; }

  /* The node itself is a button, so it carries the interactive states. */
  .soc-map__node {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    padding: 0;
    font: inherit;
    color: var(--accent-text);
    background-color: var(--bg-elevated);
    border: var(--border-width) solid var(--border-subtle);
    border-radius: 50%;
    cursor: pointer;
    transition:
      color var(--duration) var(--ease-out),
      background-color var(--duration) var(--ease-out),
      border-color var(--duration) var(--ease-out),
      transform var(--duration) var(--ease-out);
  }

  .soc-map__node:hover {
    transform: scale(1.12);
    border-color: var(--silver-accent-mid);
  }

  /* aria-pressed is the one the script maintains, so the selected node looks
     selected however it was reached — hover, Tab or tap. */
  .soc-map__node[aria-pressed="true"] {
    color: var(--on-accent);
    background-image: var(--silver-gradient-fill);
    border-color: transparent;
    box-shadow: var(--shadow);
  }

  /* In the 52-64em band the map and the card stack, so the card is centred and
     held to a comfortable measure rather than run edge to edge. */
  .layer__detail {
    width: 100%;
    max-width: 30rem;
  }
}

@media (min-width: 64em) {
  /* `auto` rather than a fixed column: the ring has three sizes and the column
     follows whichever one this panel uses. */
  .layer__viz {
    grid-template-columns: auto minmax(0, 1fr);
    justify-items: stretch;
  }

  /* Once they sit side by side the card takes everything the ring leaves,
     instead of stopping at 30rem and leaving the right of the band empty. */
  .layer__detail {
    max-width: none;
  }
}

/* --------------------------------------------------------------------------
   5. Solution cards
   -------------------------------------------------------------------------- */

.layer__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}

.tool-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-lg);
  background-color: var(--bg-elevated);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-lg);
  transition:
    transform var(--duration) var(--ease-out),
    border-color var(--duration) var(--ease-out),
    box-shadow var(--duration) var(--ease-out);
}

.tool-card:hover {
  transform: translateY(-4px);
  border-color: var(--silver-accent-mid);
  box-shadow: var(--shadow);
}

.tool-card__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
}

.tool-card__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.125rem;
  color: var(--accent-text);
  background-color: var(--bg-surface);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius);
  transition:
    color var(--duration) var(--ease-out),
    background-color var(--duration) var(--ease-out),
    border-color var(--duration) var(--ease-out);
}

.tool-card:hover .tool-card__icon {
  color: var(--on-accent);
  background-image: var(--silver-gradient-fill);
  border-color: transparent;
}

.tool-card__titles {
  min-width: 0;
}

.tool-card__name {
  margin-block-end: var(--space-3xs);
  font-size: var(--text-base);
  font-weight: 650;
}

.tool-card__category {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.tool-card__desc,
.tool-card__purpose {
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

.tool-card__label {
  display: block;
  margin-block-end: var(--space-3xs);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* The development, cloud and HRaaS data carries a second list per service —
   what the work includes, or which models it is available on. Cybersecurity
   has no equivalent, so cards there simply omit the block. */
.tool-card__features {
  display: grid;
  gap: var(--space-3xs);
  padding: 0;
  margin: 0;
  list-style: none;
}

.tool-card__feature {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3xs);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

/* Nudged down so the tick sits on the first line's baseline rather than its
   cap height, which reads as misaligned on items that wrap to two lines. */
.tool-card__check {
  flex-shrink: 0;
  margin-block-start: 0.3em;
  color: var(--accent-text);
}

/* Pushed to the bottom so the tag rows line up across a row of cards whose
   descriptions run to different lengths. */
.tool-card__toolset {
  margin-block-start: auto;
  padding-block-start: var(--space-sm);
  border-block-start: var(--border-width) solid var(--border-subtle);
}

.tool-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3xs);
  padding: 0;
  margin: 0;
  list-style: none;
}
