= htmlspecialchars($service['title']) ?>
+= htmlspecialchars($service['summary']) ?>
+-
+
+
- = htmlspecialchars($point) ?> + +
diff --git a/assets/css/custom.css b/assets/css/custom.css
index 789132e..fdf1039 100644
--- a/assets/css/custom.css
+++ b/assets/css/custom.css
@@ -1,403 +1,694 @@
-body {
- background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
- background-size: 400% 400%;
- animation: gradient 15s ease infinite;
- color: #212529;
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
- font-size: 14px;
- margin: 0;
- min-height: 100vh;
+:root {
+ --page-bg: #f4f6f8;
+ --surface: #ffffff;
+ --surface-muted: #f8fafc;
+ --ink: #0f172a;
+ --ink-soft: #475569;
+ --line: #d9e1ea;
+ --line-strong: #b8c4d4;
+ --accent: #1d4ed8;
+ --success: #0f766e;
+ --shadow: 0 16px 38px rgba(15, 23, 42, 0.06);
+ --radius-sm: 8px;
+ --radius-md: 12px;
+ --radius-lg: 16px;
+ --container-max: 1180px;
}
-.main-wrapper {
- display: flex;
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ background: var(--page-bg);
+ color: var(--ink);
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+ font-size: 15px;
+ line-height: 1.65;
+ min-height: 100vh;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+}
+
+.container {
+ max-width: var(--container-max);
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+
+a:hover {
+ color: inherit;
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+}
+
+.section-shell {
+ padding: 4.5rem 0;
+}
+
+.page-hero {
+ padding-top: 3.5rem;
+ padding-bottom: 3.5rem;
+}
+
+.site-header {
+ background: rgba(244, 246, 248, 0.92);
+ backdrop-filter: blur(14px);
+ border-bottom: 1px solid rgba(217, 225, 234, 0.85);
+ transition: box-shadow 0.2s ease, background-color 0.2s ease;
+}
+
+.site-header.is-scrolled {
+ box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
+ background: rgba(244, 246, 248, 0.97);
+}
+
+.navbar {
+ padding: 1rem 0;
+}
+
+.navbar-toggler {
+ border-color: var(--line);
+ border-radius: var(--radius-sm);
+ padding: 0.5rem 0.65rem;
+}
+
+.navbar-toggler:focus,
+.btn:focus,
+.form-control:focus,
+.form-select:focus,
+.filter-chip:focus,
+a:focus-visible,
+button:focus-visible {
+ outline: none;
+ box-shadow: 0 0 0 0.25rem rgba(29, 78, 216, 0.14);
+}
+
+.navbar-brand {
+ color: var(--ink);
+}
+
+.brand-mark {
+ width: 2.75rem;
+ height: 2.75rem;
+ display: inline-flex;
align-items: center;
justify-content: center;
- min-height: 100vh;
- width: 100%;
- padding: 20px;
- box-sizing: border-box;
- position: relative;
- z-index: 1;
-}
-
-@keyframes gradient {
- 0% {
- background-position: 0% 50%;
- }
- 50% {
- background-position: 100% 50%;
- }
- 100% {
- background-position: 0% 50%;
- }
-}
-
-.chat-container {
- width: 100%;
- max-width: 600px;
- background: rgba(255, 255, 255, 0.85);
- border: 1px solid rgba(255, 255, 255, 0.3);
- border-radius: 20px;
- display: flex;
- flex-direction: column;
- height: 85vh;
- box-shadow: 0 20px 40px rgba(0,0,0,0.2);
- backdrop-filter: blur(15px);
- -webkit-backdrop-filter: blur(15px);
- overflow: hidden;
-}
-
-.chat-header {
- padding: 1.5rem;
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
- background: rgba(255, 255, 255, 0.5);
+ border-radius: 10px;
+ background: var(--ink);
+ color: #ffffff;
+ font-size: 0.8rem;
font-weight: 700;
- font-size: 1.1rem;
- display: flex;
- justify-content: space-between;
- align-items: center;
+ letter-spacing: 0.14em;
}
-.chat-messages {
- flex: 1;
- overflow-y: auto;
- padding: 1.5rem;
- display: flex;
- flex-direction: column;
- gap: 1.25rem;
+.brand-mark--footer {
+ width: 2.5rem;
+ height: 2.5rem;
+ background: #ffffff;
+ color: var(--ink);
}
-/* Custom Scrollbar */
-::-webkit-scrollbar {
- width: 6px;
+.brand-name {
+ font-size: 0.95rem;
+ font-weight: 700;
+ letter-spacing: 0.02em;
}
-::-webkit-scrollbar-track {
+.brand-subtitle,
+.footer-muted,
+.footer-small,
+.mini-label,
+.detail-label,
+.panel-label,
+.eyebrow,
+.card-topline span,
+.hero-proof span,
+.service-badge {
+ color: var(--ink-soft);
+ font-size: 0.82rem;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+.nav-link {
+ font-size: 0.92rem;
+ font-weight: 500;
+ color: var(--ink-soft);
+ padding: 0.55rem 0.9rem !important;
+ border-radius: var(--radius-sm);
+}
+
+.nav-link:hover,
+.nav-link.active {
+ color: var(--ink);
+ background: rgba(15, 23, 42, 0.05);
+}
+
+.btn {
+ border-radius: 10px;
+ font-weight: 600;
+ padding: 0.82rem 1.15rem;
+ border-width: 1px;
+}
+
+.btn-sm {
+ padding: 0.55rem 0.9rem;
+}
+
+.btn-lg {
+ padding: 0.95rem 1.3rem;
+ font-size: 0.98rem;
+}
+
+.btn-primary {
+ background: var(--ink);
+ border-color: var(--ink);
+}
+
+.btn-primary:hover,
+.btn-primary:focus {
+ background: #09101d;
+ border-color: #09101d;
+}
+
+.btn-outline-dark {
+ border-color: var(--line-strong);
+ color: var(--ink);
background: transparent;
}
-::-webkit-scrollbar-thumb {
- background: rgba(255, 255, 255, 0.3);
- border-radius: 10px;
+.btn-outline-dark:hover,
+.btn-outline-dark:focus {
+ background: var(--surface);
+ border-color: var(--ink);
+ color: var(--ink);
}
-::-webkit-scrollbar-thumb:hover {
- background: rgba(255, 255, 255, 0.5);
+.hero-section {
+ padding-top: 5rem;
+ padding-bottom: 4rem;
}
-.message {
- max-width: 85%;
- padding: 0.85rem 1.1rem;
- border-radius: 16px;
- line-height: 1.5;
+.hero-title,
+.section-title {
+ font-size: clamp(2.3rem, 4.4vw, 4rem);
+ line-height: 1.05;
+ letter-spacing: -0.04em;
+ font-weight: 700;
+ margin: 0.85rem 0 1rem;
+ max-width: 13ch;
+}
+
+.section-title {
+ font-size: clamp(2rem, 3.6vw, 3.1rem);
+ max-width: 15ch;
+}
+
+.hero-copy,
+.section-copy,
+.footer-copy,
+.surface-panel p,
+.service-card p,
+.case-study-card p,
+.insight-card p,
+.empty-state p,
+.message-panel p {
+ color: var(--ink-soft);
+ font-size: 1rem;
+ max-width: 62ch;
+}
+
+.hero-proof span,
+.service-badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4rem;
+ padding: 0.45rem 0.75rem;
+ border: 1px solid var(--line);
+ background: var(--surface);
+ border-radius: 999px;
+ letter-spacing: 0.02em;
+ text-transform: none;
+ font-size: 0.85rem;
+}
+
+.hero-panel,
+.surface-panel,
+.metric-card,
+.service-card,
+.case-study-card,
+.insight-card,
+.process-card,
+.cta-panel,
+.empty-state {
+ background: var(--surface);
+ border: 1px solid var(--line);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow);
+}
+
+.surface-panel,
+.service-card,
+.case-study-card,
+.insight-card,
+.process-card,
+.cta-panel,
+.empty-state,
+.metric-card {
+ padding: 1.5rem;
+}
+
+.panel-heading {
+ font-size: 1.1rem;
+ font-weight: 700;
+ margin-top: 0.65rem;
+ margin-bottom: 1.2rem;
+ max-width: 18ch;
+}
+
+.panel-stack {
+ display: grid;
+ gap: 0.85rem;
+}
+
+.panel-item {
+ border: 1px solid var(--line);
+ border-radius: var(--radius-md);
+ padding: 0.95rem 1rem;
+ background: var(--surface-muted);
+}
+
+.panel-item span,
+.detail-label,
+.panel-label {
+ display: block;
+ margin-bottom: 0.35rem;
+}
+
+.panel-item strong,
+.metric-card strong,
+.reference-code,
+.detail-grid strong {
+ font-size: 1rem;
+ font-weight: 700;
+ color: var(--ink);
+}
+
+.hero-note {
+ margin-top: 1.1rem;
+ color: var(--ink-soft);
font-size: 0.95rem;
- box-shadow: 0 4px 15px rgba(0,0,0,0.05);
- animation: fadeIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
-@keyframes fadeIn {
- from { opacity: 0; transform: translateY(20px) scale(0.95); }
- to { opacity: 1; transform: translateY(0) scale(1); }
-}
-
-.message.visitor {
- align-self: flex-end;
- background: linear-gradient(135deg, #212529 0%, #343a40 100%);
- color: #fff;
- border-bottom-right-radius: 4px;
-}
-
-.message.bot {
- align-self: flex-start;
- background: #ffffff;
- color: #212529;
- border-bottom-left-radius: 4px;
-}
-
-.chat-input-area {
- padding: 1.25rem;
- background: rgba(255, 255, 255, 0.5);
- border-top: 1px solid rgba(0, 0, 0, 0.05);
-}
-
-.chat-input-area form {
- display: flex;
- gap: 0.75rem;
-}
-
-.chat-input-area input {
- flex: 1;
- border: 1px solid rgba(0, 0, 0, 0.1);
- border-radius: 12px;
- padding: 0.75rem 1rem;
- outline: none;
- background: rgba(255, 255, 255, 0.9);
- transition: all 0.3s ease;
-}
-
-.chat-input-area input:focus {
- border-color: #23a6d5;
- box-shadow: 0 0 0 3px rgba(35, 166, 213, 0.2);
-}
-
-.chat-input-area button {
- background: #212529;
- color: #fff;
- border: none;
- padding: 0.75rem 1.5rem;
- border-radius: 12px;
- cursor: pointer;
- font-weight: 600;
- transition: all 0.3s ease;
-}
-
-.chat-input-area button:hover {
- background: #000;
- transform: translateY(-2px);
- box-shadow: 0 5px 15px rgba(0,0,0,0.2);
-}
-
-/* Background Animations */
-.bg-animations {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 0;
- overflow: hidden;
- pointer-events: none;
-}
-
-.blob {
- position: absolute;
- width: 500px;
- height: 500px;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 50%;
- filter: blur(80px);
- animation: move 20s infinite alternate cubic-bezier(0.45, 0, 0.55, 1);
-}
-
-.blob-1 {
- top: -10%;
- left: -10%;
- background: rgba(238, 119, 82, 0.4);
-}
-
-.blob-2 {
- bottom: -10%;
- right: -10%;
- background: rgba(35, 166, 213, 0.4);
- animation-delay: -7s;
- width: 600px;
- height: 600px;
-}
-
-.blob-3 {
- top: 40%;
- left: 30%;
- background: rgba(231, 60, 126, 0.3);
- animation-delay: -14s;
- width: 450px;
- height: 450px;
-}
-
-@keyframes move {
- 0% { transform: translate(0, 0) rotate(0deg) scale(1); }
- 33% { transform: translate(150px, 100px) rotate(120deg) scale(1.1); }
- 66% { transform: translate(-50px, 200px) rotate(240deg) scale(0.9); }
- 100% { transform: translate(0, 0) rotate(360deg) scale(1); }
-}
-
-.header-link {
- font-size: 14px;
- color: #fff;
- text-decoration: none;
- background: rgba(0, 0, 0, 0.2);
- padding: 0.5rem 1rem;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.header-link:hover {
- background: rgba(0, 0, 0, 0.4);
- text-decoration: none;
-}
-
-/* Admin Styles */
-.admin-container {
- max-width: 900px;
- margin: 3rem auto;
- padding: 2.5rem;
- background: rgba(255, 255, 255, 0.85);
- backdrop-filter: blur(20px);
- -webkit-backdrop-filter: blur(20px);
- border-radius: 24px;
- box-shadow: 0 20px 50px rgba(0,0,0,0.15);
- border: 1px solid rgba(255, 255, 255, 0.4);
- position: relative;
- z-index: 1;
-}
-
-.admin-container h1 {
- margin-top: 0;
- color: #212529;
- font-weight: 800;
-}
-
-.table {
- width: 100%;
- border-collapse: separate;
- border-spacing: 0 8px;
+.stats-row {
margin-top: 1.5rem;
}
-.table th {
- background: transparent;
- border: none;
- padding: 1rem;
- color: #6c757d;
- font-weight: 600;
- text-transform: uppercase;
- font-size: 0.75rem;
- letter-spacing: 1px;
+.metric-card {
+ height: 100%;
+ background: rgba(255, 255, 255, 0.92);
}
-.table td {
- background: #fff;
- padding: 1rem;
- border: none;
-}
-
-.table tr td:first-child { border-radius: 12px 0 0 12px; }
-.table tr td:last-child { border-radius: 0 12px 12px 0; }
-
-.form-group {
- margin-bottom: 1.25rem;
-}
-
-.form-group label {
+.metric-card strong {
display: block;
- margin-bottom: 0.5rem;
- font-weight: 600;
- font-size: 0.9rem;
+ font-size: 1.25rem;
+ margin-bottom: 0.2rem;
+ letter-spacing: -0.03em;
}
-.form-control {
- width: 100%;
- padding: 0.75rem 1rem;
- border: 1px solid rgba(0, 0, 0, 0.1);
- border-radius: 12px;
- background: #fff;
- transition: all 0.3s ease;
- box-sizing: border-box;
+.metric-card span {
+ display: block;
+ color: var(--ink-soft);
+ font-size: 0.92rem;
}
-.form-control:focus {
- outline: none;
- border-color: #23a6d5;
- box-shadow: 0 0 0 3px rgba(35, 166, 213, 0.1);
+.section-heading-row {
+ margin-bottom: 1rem;
}
-.header-container {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.header-links {
+.service-card,
+.case-study-card,
+.insight-card {
display: flex;
+ flex-direction: column;
gap: 1rem;
}
-.admin-card {
- background: rgba(255, 255, 255, 0.6);
- padding: 2rem;
- border-radius: 20px;
- border: 1px solid rgba(255, 255, 255, 0.5);
- margin-bottom: 2.5rem;
- box-shadow: 0 10px 30px rgba(0,0,0,0.05);
-}
-
-.admin-card h3 {
- margin-top: 0;
- margin-bottom: 1.5rem;
+.service-card h3,
+.case-study-card h3,
+.insight-card h3,
+.content-row h3,
+.process-card h3,
+.detail-list-item h2,
+.article-section h2 {
+ font-size: 1.12rem;
+ line-height: 1.35;
font-weight: 700;
+ margin: 0;
+ letter-spacing: -0.02em;
}
-.btn-delete {
- background: #dc3545;
- color: white;
- border: none;
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- cursor: pointer;
+.service-points,
+.detail-list,
+.detail-grid,
+.process-grid {
+ display: grid;
+ gap: 0.95rem;
}
-.btn-add {
- background: #212529;
- color: white;
- border: none;
- padding: 0.5rem 1rem;
- border-radius: 4px;
- cursor: pointer;
- margin-top: 1rem;
+.service-points li {
+ position: relative;
+ padding-left: 1.2rem;
+ color: var(--ink-soft);
}
-.btn-save {
- background: #0088cc;
- color: white;
- border: none;
- padding: 0.8rem 1.5rem;
- border-radius: 12px;
- cursor: pointer;
+.service-points li::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0.62rem;
+ width: 0.4rem;
+ height: 0.4rem;
+ border-radius: 999px;
+ background: var(--ink);
+}
+
+.compact-panel .content-row,
+.detail-list-item,
+.article-section {
+ padding-bottom: 1rem;
+ border-bottom: 1px solid var(--line);
+ margin-bottom: 1rem;
+}
+
+.compact-panel .content-row:last-child,
+.detail-list-item:last-child,
+.article-section:last-child {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom: 0;
+}
+
+.process-grid {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.process-card {
+ min-height: 100%;
+}
+
+.process-index {
+ width: 2rem;
+ height: 2rem;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ background: var(--ink);
+ color: #ffffff;
+ font-size: 0.78rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ margin-bottom: 1rem;
+}
+
+.card-topline {
+ display: flex;
+ justify-content: space-between;
+ gap: 0.75rem;
+ align-items: center;
+}
+
+.result-pills {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.6rem;
+}
+
+.result-pills span {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.48rem 0.72rem;
+ border-radius: 999px;
+ background: var(--surface-muted);
+ border: 1px solid var(--line);
+ color: var(--ink-soft);
+ font-size: 0.88rem;
+}
+
+.result-pills--large span {
+ font-size: 0.92rem;
+}
+
+.text-link,
+.crumb-link {
font-weight: 600;
- width: 100%;
- transition: all 0.3s ease;
+ color: var(--ink);
}
-.webhook-url {
- font-size: 0.85em;
- color: #555;
- margin-top: 0.5rem;
+.text-link:hover,
+.crumb-link:hover {
+ color: var(--accent);
}
-.history-table-container {
- overflow-x: auto;
- background: rgba(255, 255, 255, 0.4);
+.filter-toolbar {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ margin-bottom: 1rem;
+}
+
+.filter-chip {
+ border: 1px solid var(--line);
+ border-radius: 999px;
+ background: var(--surface);
+ color: var(--ink-soft);
+ font-size: 0.88rem;
+ padding: 0.6rem 0.9rem;
+ font-weight: 600;
+ transition: all 0.2s ease;
+}
+
+.filter-chip:hover,
+.filter-chip.is-active {
+ border-color: var(--ink);
+ color: var(--ink);
+ background: var(--surface-muted);
+}
+
+[data-filter-item].is-hidden {
+ display: none !important;
+}
+
+.form-panel {
+ padding: 1.75rem;
+}
+
+.form-label {
+ font-size: 0.88rem;
+ font-weight: 600;
+ color: var(--ink);
+ margin-bottom: 0.45rem;
+}
+
+.form-control,
+.form-select {
+ min-height: 3rem;
+ border-radius: 10px;
+ border-color: var(--line-strong);
+ background: var(--surface);
+ color: var(--ink);
+ padding: 0.75rem 0.9rem;
+}
+
+textarea.form-control {
+ min-height: 10rem;
+ resize: vertical;
+}
+
+.form-control::placeholder {
+ color: #8fa0b5;
+}
+
+.reference-code {
+ font-size: 1.5rem;
+ letter-spacing: 0.08em;
+}
+
+.detail-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.detail-grid > div,
+.message-panel {
+ border: 1px solid var(--line);
+ border-radius: var(--radius-md);
padding: 1rem;
+ background: var(--surface-muted);
+}
+
+.message-panel p {
+ margin: 0;
+}
+
+.quote-panel {
+ border-left: 3px solid var(--ink);
+ padding-left: 1rem;
+}
+
+.quote-panel p {
+ font-size: 1.05rem;
+ color: var(--ink);
+ margin-bottom: 0.45rem;
+}
+
+.quote-panel span {
+ color: var(--ink-soft);
+ font-size: 0.9rem;
+}
+
+.cta-panel {
+ display: flex;
+ gap: 1.5rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.site-footer {
+ background: var(--ink);
+ color: #ffffff;
+ border-color: rgba(255, 255, 255, 0.08) !important;
+}
+
+.site-footer .footer-copy,
+.site-footer .footer-muted,
+.site-footer .footer-small,
+.site-footer .footer-links a {
+ color: rgba(255, 255, 255, 0.72);
+}
+
+.footer-links {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ justify-content: flex-start;
+}
+
+.footer-links a:hover {
+ color: #ffffff;
+}
+
+.site-toast {
+ border: 1px solid rgba(15, 23, 42, 0.12);
border-radius: 12px;
- border: 1px solid rgba(255, 255, 255, 0.3);
+ box-shadow: 0 20px 40px rgba(15, 23, 42, 0.18);
}
-.history-table {
- width: 100%;
+.toast-header {
+ background: #ffffff;
+ color: var(--ink);
}
-.history-table-time {
- width: 15%;
- white-space: nowrap;
- font-size: 0.85em;
- color: #555;
+.toast-body {
+ background: var(--surface);
+ color: var(--ink-soft);
}
-.history-table-user {
- width: 35%;
- background: rgba(255, 255, 255, 0.3);
- border-radius: 8px;
- padding: 8px;
+.toast-dot {
+ width: 0.6rem;
+ height: 0.6rem;
+ border-radius: 999px;
+ background: var(--success);
+ display: inline-block;
+ margin-right: 0.5rem;
}
-.history-table-ai {
- width: 50%;
- background: rgba(255, 255, 255, 0.5);
- border-radius: 8px;
- padding: 8px;
-}
-
-.no-messages {
+.empty-state {
text-align: center;
- color: #777;
-}
\ No newline at end of file
+ padding: 2.5rem;
+}
+
+.empty-state--page {
+ max-width: 720px;
+ margin: 0 auto;
+}
+
+.empty-state h1,
+.empty-state h2 {
+ font-size: 1.8rem;
+ line-height: 1.2;
+ letter-spacing: -0.03em;
+ margin-bottom: 0.75rem;
+}
+
+.article-panel {
+ padding: 1.75rem;
+}
+
+.article-section p {
+ margin-bottom: 0;
+}
+
+.alert {
+ border-radius: 12px;
+ border-width: 1px;
+}
+
+@media (max-width: 991.98px) {
+ .section-shell {
+ padding: 3.5rem 0;
+ }
+
+ .hero-section {
+ padding-top: 4rem;
+ }
+
+ .process-grid,
+ .detail-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .cta-panel {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .footer-links {
+ justify-content: flex-start;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .section-title,
+ .hero-title {
+ max-width: none;
+ }
+
+ .surface-panel,
+ .service-card,
+ .case-study-card,
+ .insight-card,
+ .process-card,
+ .cta-panel,
+ .empty-state,
+ .metric-card {
+ padding: 1.25rem;
+ }
+
+ .hero-proof {
+ gap: 0.55rem !important;
+ }
+
+ .hero-proof span,
+ .service-badge {
+ width: 100%;
+ justify-content: flex-start;
+ }
+}
diff --git a/assets/js/main.js b/assets/js/main.js
index d349598..df50818 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -1,39 +1,99 @@
document.addEventListener('DOMContentLoaded', () => {
- const chatForm = document.getElementById('chat-form');
- const chatInput = document.getElementById('chat-input');
- const chatMessages = document.getElementById('chat-messages');
+ const header = document.querySelector('.site-header');
+ const toastElement = document.getElementById('siteToast');
+ const toastBody = toastElement ? toastElement.querySelector('.toast-body') : null;
+ const pageToastMessage = document.body.dataset.toastMessage || '';
- const appendMessage = (text, sender) => {
- const msgDiv = document.createElement('div');
- msgDiv.classList.add('message', sender);
- msgDiv.textContent = text;
- chatMessages.appendChild(msgDiv);
- chatMessages.scrollTop = chatMessages.scrollHeight;
+ const showToast = (message) => {
+ if (!toastElement || !toastBody || !window.bootstrap) {
+ return;
+ }
+ toastBody.textContent = message;
+ window.bootstrap.Toast.getOrCreateInstance(toastElement, { delay: 3000 }).show();
};
- chatForm.addEventListener('submit', async (e) => {
- e.preventDefault();
- const message = chatInput.value.trim();
- if (!message) return;
+ if (header) {
+ const toggleHeaderState = () => {
+ header.classList.toggle('is-scrolled', window.scrollY > 10);
+ };
+ toggleHeaderState();
+ window.addEventListener('scroll', toggleHeaderState, { passive: true });
+ }
- appendMessage(message, 'visitor');
- chatInput.value = '';
+ if (pageToastMessage) {
+ showToast(pageToastMessage);
+ }
- try {
- const response = await fetch('api/chat.php', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ message })
+ document.querySelectorAll('[data-copy-target]').forEach((button) => {
+ button.addEventListener('click', async () => {
+ const target = document.querySelector(button.dataset.copyTarget || '');
+ if (!target) {
+ return;
+ }
+
+ const value = target.textContent.trim();
+ if (!value) {
+ return;
+ }
+
+ try {
+ await navigator.clipboard.writeText(value);
+ showToast('Reference copied to clipboard.');
+ } catch (error) {
+ showToast('Copy is unavailable in this browser.');
+ }
+ });
+ });
+
+ document.querySelectorAll('[data-filter-group]').forEach((group) => {
+ const targetSelector = group.dataset.filterTarget;
+ const emptySelector = group.dataset.emptyState;
+ const resetButton = document.querySelector('[data-reset-filter]');
+ const target = targetSelector ? document.querySelector(targetSelector) : null;
+ const emptyState = emptySelector ? document.querySelector(emptySelector) : null;
+ const buttons = Array.from(group.querySelectorAll('[data-filter]'));
+ const items = target ? Array.from(target.querySelectorAll('[data-filter-item]')) : [];
+
+ if (!target || buttons.length === 0 || items.length === 0) {
+ return;
+ }
+
+ const applyFilter = (filter) => {
+ let visibleCount = 0;
+ items.forEach((item) => {
+ const matches = filter === 'all' || item.dataset.filterItem === filter;
+ item.classList.toggle('is-hidden', !matches);
+ if (matches) {
+ visibleCount += 1;
+ }
});
- const data = await response.json();
-
- // Artificial delay for realism
- setTimeout(() => {
- appendMessage(data.reply, 'bot');
- }, 500);
- } catch (error) {
- console.error('Error:', error);
- appendMessage("Sorry, something went wrong. Please try again.", 'bot');
+
+ buttons.forEach((button) => {
+ button.classList.toggle('is-active', button.dataset.filter === filter);
+ });
+
+ if (emptyState) {
+ emptyState.classList.toggle('d-none', visibleCount > 0);
+ }
+ };
+
+ buttons.forEach((button) => {
+ button.addEventListener('click', () => applyFilter(button.dataset.filter || 'all'));
+ });
+
+ if (resetButton) {
+ resetButton.addEventListener('click', () => applyFilter('all'));
}
});
+
+ const navbarCollapse = document.getElementById('primaryNav');
+ if (navbarCollapse && window.bootstrap) {
+ document.querySelectorAll('#primaryNav .nav-link').forEach((link) => {
+ link.addEventListener('click', () => {
+ if (window.innerWidth < 992) {
+ window.bootstrap.Collapse.getOrCreateInstance(navbarCollapse).hide();
+ }
+ });
+ });
+ }
});
diff --git a/brief.php b/brief.php
new file mode 100644
index 0000000..4a6d941
--- /dev/null
+++ b/brief.php
@@ -0,0 +1,125 @@
+getMessage());
+ $loadError = 'We could not load that brief right now.';
+ }
+}
+
+require __DIR__ . '/partials/header.php';
+?>
+ Use the reference below if you want to discuss this brief internally or when we wire notifications next. Start a new project brief and we will capture the details from there. We review the brief against scope, urgency, and likely team shape. We recommend a discovery sprint, delivery pod, or a smaller technical diligence engagement. Share the reference with stakeholders or continue exploring our work and insights. The selected case study is unavailable. You can return to the work overview and choose another representative engagement. = htmlspecialchars($study['summary']) ?> = htmlspecialchars($study['client']) ?> · = htmlspecialchars($study['engagement']) ?> = htmlspecialchars($study['timeline']) ?> = htmlspecialchars($item) ?> = htmlspecialchars($item) ?> “= htmlspecialchars($study['quote']) ?>” This first form is intentionally concise. It gives us enough context to propose the right engagement model, timeline, and next conversation. We assess scope, urgency, and likely delivery shape within one business day. If there is a fit, we use the first call to refine goals, constraints, and success metrics. You receive a pragmatic recommendation: discovery sprint, delivery pod, or a smaller advisory step. Review our representative work and editorial thinking before sending a brief.Your request is in the queue.
+ We could not find that brief.
+ Internal review
+ Response path
+ What you can do now
+ Case study not found
+ = htmlspecialchars($study['title']) ?>
+ Client profile
+ Timeline
+ = htmlspecialchars($study['client']) ?> needed a lower-risk path forward
+ What we changed
+ Tell us what you are building and we will shape the next step.
+ 1. Brief review
+ 2. Working session
+ 3. Clear recommendation
+
+
+
We help founders, product teams, and enterprise leaders design, build, and modernize software that needs to move with confidence. Strategy, delivery, and communication stay crisp from day one.
+ += ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.
-This page will update automatically as the plan is implemented.
-Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
Whether you need a new product, a cleaner architecture, or a more resilient operating system, we focus on the smallest move that creates durable leverage.
+= htmlspecialchars($service['summary']) ?>
+We combine strategic clarity with hands-on execution so leadership gets confidence without needing to chase updates.
+= htmlspecialchars($principle['body']) ?>
+= htmlspecialchars($step['body']) ?>
+= htmlspecialchars($study['summary']) ?>
+= htmlspecialchars($article['excerpt']) ?>
+ Read article +Send a short brief and we will shape the next steps around your business context, not a generic process.
+The article you requested is unavailable. You can return to the insights overview and pick another piece.
+ Back to insights += htmlspecialchars($article['excerpt']) ?>
+= htmlspecialchars(format_display_date($article['published'])) ?> · = htmlspecialchars($article['read_time']) ?>
+= htmlspecialchars($section['body']) ?>
+Want to apply this thinking to a live roadmap?
+ Start a project brief +A library of practical guidance on product strategy, delivery discipline, and how to move faster without creating unnecessary risk.
+What to build, what to defer, and how to protect launch velocity.
+Communication patterns, risk review, and release planning for complex programs.
+Where custom software creates strategic leverage and where it does not.
+= htmlspecialchars($article['excerpt']) ?>
+