blob: cb462c11e725b37cf2dcc52b387c23b3de7dafe4 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* ===== Window frame — same chrome as the landing code windows ============ */
.model {
border: 1px solid var(--odl-border);
border-radius: var(--odl-radius-lg);
background: var(--odl-surface);
box-shadow: var(--odl-shadow-lg);
overflow: hidden;
margin: var(--odl-space-6) 0;
}
.windowBar {
display: flex;
align-items: center;
gap: var(--odl-space-3);
padding: var(--odl-space-3) var(--odl-space-4);
border-bottom: 1px solid var(--odl-border);
background: var(--odl-surface-2);
}
.windowDots {
display: flex;
gap: 6px;
}
.windowDots span {
width: 11px;
height: 11px;
border-radius: var(--odl-radius-pill);
background: var(--odl-border-strong);
}
.windowTitle {
flex: 1 1 auto;
min-width: 0;
font-family: var(--odl-font-mono);
font-size: var(--odl-text-xs);
color: var(--odl-fg-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* ===== Diagram =========================================================== */
.diagram {
position: relative;
display: flex;
align-items: center;
gap: var(--odl-space-4);
padding: clamp(2rem, 1.5rem + 2vw, 3rem) clamp(1.25rem, 1rem + 1.5vw, 2rem);
background: var(--odl-bg);
}
/* Blueprint grid fading out from the top, as on the landing hero. */
.gridLayer {
position: absolute;
inset: 0;
pointer-events: none;
-webkit-mask-image: radial-gradient(
110% 100% at 50% 0%,
#000 0%,
transparent 78%
);
mask-image: radial-gradient(110% 100% at 50% 0%, #000 0%, transparent 78%);
}
.app,
.flow,
.ringOuter,
.backend {
position: relative;
transition: opacity var(--odl-dur) var(--odl-ease);
}
.app,
.service {
display: flex;
flex-direction: column;
gap: 4px;
padding: var(--odl-space-3) var(--odl-space-4);
border: 1px solid var(--odl-border-strong);
border-radius: var(--odl-radius-md);
background: var(--odl-surface);
box-shadow: var(--odl-shadow-sm);
transition: border-color var(--odl-dur) var(--odl-ease);
}
.comment {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-2xs);
color: var(--odl-fg-subtle);
white-space: nowrap;
}
.code {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-xs);
color: var(--odl-fg);
background: none;
border: 0;
padding: 0;
white-space: nowrap;
}
/* Connectors: hairlines converging on the operator. The build arrow points
right (config flows in), the call arrow points left (the app calls in). */
.flow {
flex: 1 1 1.5rem;
min-width: 1.25rem;
height: 1px;
background: var(--odl-border-strong);
}
.flow::after {
content: "";
position: absolute;
width: 7px;
height: 7px;
border-top: 1px solid var(--odl-border-strong);
border-right: 1px solid var(--odl-border-strong);
transition: border-color var(--odl-dur) var(--odl-ease);
}
.flowBuild::after {
right: 0;
top: -3.5px;
transform: rotate(45deg);
}
.flowCall::after {
left: 0;
top: -3.5px;
transform: rotate(-135deg);
}
.flowLabel {
position: absolute;
left: 50%;
bottom: 5px;
transform: translateX(-50%);
font-family: var(--odl-font-mono);
font-size: var(--odl-text-2xs);
letter-spacing: 0.04em;
color: var(--odl-fg-subtle);
transition: color var(--odl-dur) var(--odl-ease);
}
/* Layers wrap the operator as light, dashed envelopes; the operator stays
the only solid mass in the middle. */
.ringOuter,
.ringInner {
display: flex;
flex-direction: column;
gap: 4px;
padding: var(--odl-space-2) var(--odl-space-3) var(--odl-space-3);
border: 1px dashed var(--odl-border-strong);
transition: border-color var(--odl-dur) var(--odl-ease);
}
.ringOuter {
border-radius: var(--odl-radius-lg);
background: transparent;
}
.ringInner {
border-radius: var(--odl-radius-md);
background: var(--odl-surface);
box-shadow: var(--odl-shadow-sm);
}
.ringLabel {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-2xs);
color: var(--odl-fg-muted);
white-space: nowrap;
transition: color var(--odl-dur) var(--odl-ease),
opacity var(--odl-dur) var(--odl-ease);
}
/* "kind ·" prefix inside labels: quiet type, louder instance. */
.kind {
font-weight: 400;
color: var(--odl-fg-subtle);
transition: color var(--odl-dur) var(--odl-ease);
}
/* The operator is the solid "bar" at the center of the model. */
.core {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-sm);
font-weight: 600;
text-align: center;
padding: var(--odl-space-3) var(--odl-space-6);
border-radius: var(--odl-radius-sm);
background: var(--odl-bar);
color: var(--odl-bg);
box-shadow: var(--odl-shadow-md);
transition: opacity var(--odl-dur) var(--odl-ease),
box-shadow var(--odl-dur) var(--odl-ease);
}
.backend {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--odl-space-2);
}
.svcName {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-xs);
font-weight: 600;
color: var(--odl-fg-strong);
transition: color var(--odl-dur) var(--odl-ease);
}
.alts {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-2xs);
color: var(--odl-fg-subtle);
padding-left: 2px;
white-space: nowrap;
transition: color var(--odl-dur) var(--odl-ease);
}
/* ===== Highlight states ================================================== */
/* service */
.model[data-active="service"] .app,
.model[data-active="service"] .flow,
.model[data-active="service"] .ringOuter {
opacity: 0.35;
}
.model[data-active="service"] .service {
border-color: var(--odl-accent);
}
.model[data-active="service"] .svcName,
.model[data-active="service"] .svcName .kind {
color: var(--odl-accent);
}
.model[data-active="service"] .alts {
color: var(--odl-fg-muted);
}
/* operator */
.model[data-active="operator"] .app,
.model[data-active="operator"] .flow,
.model[data-active="operator"] .backend {
opacity: 0.35;
}
.model[data-active="operator"] .ringOuter,
.model[data-active="operator"] .ringInner {
border-color: var(--odl-border);
}
.model[data-active="operator"] .ringLabel {
opacity: 0.4;
}
.model[data-active="operator"] .core {
box-shadow: 0 0 0 2px var(--odl-accent), var(--odl-shadow-md);
}
/* layer */
.model[data-active="layer"] .app,
.model[data-active="layer"] .flow,
.model[data-active="layer"] .backend {
opacity: 0.35;
}
.model[data-active="layer"] .ringOuter,
.model[data-active="layer"] .ringInner {
border-color: var(--odl-accent);
}
.model[data-active="layer"] .ringLabel,
.model[data-active="layer"] .ringLabel .kind {
color: var(--odl-accent);
}
.model[data-active="layer"] .core {
opacity: 0.5;
}
/* operation */
.model[data-active="operation"] .app {
border-color: var(--odl-accent);
}
.model[data-active="operation"] .flow {
background: var(--odl-accent);
}
.model[data-active="operation"] .flow::after {
border-color: var(--odl-accent);
}
.model[data-active="operation"] .flowLabel {
color: var(--odl-accent);
}
/* ===== Legend — one compact row, tab-style accent indicator ============= */
.legend {
display: flex;
flex-wrap: wrap;
margin: 0;
border-top: 1px solid var(--odl-border);
background: var(--odl-surface-2);
}
.legendItem {
appearance: none;
font: inherit;
flex: 1 1 25%;
display: flex;
align-items: baseline;
justify-content: center;
gap: var(--odl-space-2);
padding: var(--odl-space-3) var(--odl-space-2);
border: 0;
border-top: 2px solid transparent;
background: transparent;
cursor: pointer;
transition: background-color var(--odl-dur) var(--odl-ease),
border-color var(--odl-dur) var(--odl-ease);
}
.legendItem:hover {
background: var(--odl-surface);
}
.legendItemActive {
background: var(--odl-surface);
border-top-color: var(--odl-accent);
}
.legendIndex {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-2xs);
font-weight: 500;
letter-spacing: var(--odl-tracking-label);
color: var(--odl-fg-subtle);
transition: color var(--odl-dur) var(--odl-ease);
}
.legendItemActive .legendIndex {
color: var(--odl-accent);
}
.legendName {
font-family: var(--odl-font-mono);
font-size: var(--odl-text-sm);
font-weight: 600;
color: var(--odl-fg-muted);
transition: color var(--odl-dur) var(--odl-ease);
}
.legendItemActive .legendName {
color: var(--odl-fg-strong);
}
/* ===== Responsive ======================================================== */
@media (max-width: 768px) {
.diagram {
flex-direction: column;
align-items: stretch;
}
.app,
.ringOuter,
.backend {
align-self: center;
}
.flow {
flex: 0 0 auto;
align-self: center;
width: 1px;
min-width: 0;
height: 1.5rem;
min-height: 1.5rem;
}
/* Stacked: build points down into the operator, call points up from the
app at the bottom. */
.flowBuild::after {
right: -3.5px;
top: auto;
bottom: 0;
transform: rotate(135deg);
}
.flowCall::after {
left: -3.5px;
top: 0;
transform: rotate(-45deg);
}
.flowLabel {
left: 10px;
bottom: auto;
top: 50%;
transform: translateY(-50%);
}
.legendItem {
flex-basis: 50%;
}
}